1、io的基本概念
I/O操作指的是進行輸入、輸出的操作,輸入/輸出操作都是基於數據流的,這些數據流表示了字節或字符流動的序列。Java中的I/O流提供了讀寫數據的標準方法,任何表示數據源的對象都會以數據流的方式讀寫它的數據方法。
java把用於操作輸入/輸出的類放在java.io包中。
2、io流的分類
按照流的方向分,可以分爲輸入流和輸出流
- 輸入流:從外部讀入數據到內存,外部可以是磁盤、網絡等。
- 輸出流:將數據從內存寫出到外部。
NOTE:我們這裏的輸入/輸出可以從程序運行所在內存的角度來看,輸入/輸出的方向是單向的。
按照數據流的類性,可以分爲字節流和字符流
字節流和字符流的不同之處在於操作數據單元的大小不同,字節流操作的數據單元是8位的字節,字符流操作的數據單元是16位的字符。
按處理流的方式,可以分爲節點流和處理流。
- 節點流:也可被稱爲低級流,它和數據源直接對接
- 高級流:建立在低級流的基礎上,對已存在的流進行連接和封裝,通過封裝後的流實現數據的讀寫功能。
3、Java中常用的IO類
接下來我們按照輸入/輸出流的方式講解
3.1四個抽象類
InputStrem | 以字節爲單位的輸入流 |
---|---|
OutputStream | 以字節爲單位的輸出流 |
Reader | 以字符爲單位的輸入流 |
Writer | 以字符爲單位的輸出流 |
這四個抽象類是所有輸入/輸出流的基類,它們中定義的方法用於操作數據流的傳輸
- InputStream和Reader
read():從輸入流中讀取單個字節/字符,並返回讀取的字節/字符數據
read(byte/char b[]):從輸入流中最多讀取b.length個字節/字符,將其存儲在數組b中,並返回讀取的字節/字符數據
read(byte/char b[], int off, int len):從輸入流中最多讀取len字節/字符,將其存儲在數組b中,並返回讀取的字節/字符數據,讀取字節/字符的起點從off開始
以InputStream爲例,具體代碼如下
/**
*從輸入流中讀取單個字節,並返回讀取的字節數據
*/
public abstract int read();
/**
*從輸入流中最多讀取b.length個字節,將其存儲在數組b中,並返回讀取的字節數據
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
*從輸入流中最多讀取len字節,將其存儲在數組b中,並返回讀取的字節數據,讀取字節的起點從off開始
*/
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
Reader內的方法和InputStream內的方法類似,只是將byte換成了char
- OutputStream和Writer
write(int b):將指定的字節/字符輸出到輸出流中
write(byte/char b[]):將字節/字符數組中的數據輸出到輸出流中
write(byte/char b[], int off, int len):將起始點爲off,長度爲len的字節/字符數組中的數據輸出到輸出流中。
以OutPutStream爲例
public abstract void write(int b);
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}
3.2輸入操作
FileInputStream | 文件輸入流,用於從文件系統中獲得輸入字節 |
---|---|
FileReader | 對文件的讀取,獲取字符流 |
以FileInputStream爲例,FileReader的實現和FileInputStream相同,只是操作單位不同
public class testInput {
public static void main(String[] args) throws Exception{
FileInputStream fis=null;
try {
//創建字節輸入流
fis=new FileInputStream("F:\\學習筆記\\Simon學習筆記\\java\\test.txt");
//創建一個長度爲1024的byte數組
byte[] b=new byte[1024];
//用於保存的實際字節數
int count=0;
//重複讀取,直到去完爲止
while ((count=fis.read(b))>0){
//轉成字符串進行輸出
System.out.println(new String(b,0,count));
}
}catch (IOException e){
e.printStackTrace();
}finally {
fis.close();
}
}
}
Note:字節讀取結束的條件是方法read方法返回了-1;所以我們可以用(count=fis.read(b))>0進行判斷,
因爲IO不屬於內存資源,需要手動關閉。但是java7引入了try(resource)的語法,只需要編寫try語句,就可以讓編譯器自動的爲我們關閉資源
所以代碼可以改寫爲
try( fis=new FileInputStream("F:\\學習筆記\\Simon學習筆記\\java\\test.txt")) {
//創建一個長度爲1024的byte數組
byte[] b=new byte[1024];
//用於保存的實際字節數
int count=0;
//重複讀取,直到去完爲止
while ((count=fis.read(b))>0){
//轉成字符串進行輸出
System.out.println(new String(b,0,count));
}//編譯器在此自動爲我們寫入finally並調用close
3.3輸出操作
FileOutputStream | 文件輸出流,用於將數據寫入File的輸出流,字節流 |
---|---|
FileWriter | 用於對文件的寫入操作,字符流 |
以FileOutputStream爲例,同理,FileWriter也是一樣,只是操作單位不一樣。
public class testOutPut {
public static void main(String[] args) throws IOException {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
//創建字節輸入流
fis=new FileInputStream("F:\\學習筆記\\Simon學習筆記\\java\\test.txt");
//創建字符
fos=new FileOutputStream("F:\\學習筆記\\Simon學習筆記\\java\\test2.txt");
byte[] b=new byte[1024];
int count=0;
while((count=fis.read(b))>0){
fos.write(b,0,count);
}
}catch (IOException e){
e.printStackTrace();
}finally {
fis.close();
fos.close();
}
}
}
3.4緩存流的使用
爲什麼需要緩存流:
一塊緩存區可以理解爲塊操作,如今處理器支持按照塊來讀取數據,這會使得讀取次數變少,進而提高性能。
BufferedInputStream | 爲輸入流提供緩衝功能 |
---|---|
BufferedOutputStream | 爲輸出流提供緩衝功能 |
BufferedReader | 爲輸入流提供緩衝功能 |
BufferedWriter | 爲輸出流提供緩衝功能 |
public class testBuffer {
public static void main(String[] args)throws IOException {
FileInputStream fis=null;
FileOutputStream fos=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
//創建字節輸入流
fis=new FileInputStream("F:\\學習筆記\\Simon學習筆記\\java\\test.txt");
//創建字節輸出流
fos=new FileOutputStream("F:\\學習筆記\\Simon學習筆記\\java\\test3.txt");
//創建字節緩存輸入流
bis=new BufferedInputStream(fis);
//創建字節緩存輸出流
bos=new BufferedOutputStream(fos);
byte[] b=new byte[1024];
int count=0;
//循環從緩存流中讀取數據
while((count=bis.read(b))>0){
//向緩存流中寫入數據,讀取多少寫入多少
bos.write(b,0,count);
}
}catch (IOException e){
e.printStackTrace();
}finally {
bis.close();
bos.close();
}
}
}
關注公衆號:10分鐘編程,回覆success,贈送你尚硅谷,黑馬的Java和大數據視頻。