IO流

IO流

什麼是IO流呢?就是用與處理設備之間數據傳輸的!
傳輸的方式無非就是兩種,不是讀數據就是寫數據!
先來介紹一下用來操作IO流的主要對象:
按照流向分爲輸入流和輸出流。
IO流的對象都存在IO包中,如果按照操作數據分爲:字節流和字符流
根據下面這張圖來進行了解:
這裏寫圖片描述

字符流


Reader:用於讀取字符流的抽象類。子類必須實現的方法只有 read(char[], int, int) 和 close()。
|—BufferedReader:從字符輸入流中讀取文本,緩衝各個字符,從而實現字符、數組和行的高效讀取。 可以指定緩衝區的大小,或者可使用默認的大小。大多數情況下,默認值就足夠大了。
|—LineNumberReader:跟蹤行號的緩衝字符輸入流。此類定義了方法 setLineNumber(int) 和 getLineNumber(),它們可分別用於設置和獲取當前行號。
|—InputStreamReader:是字節流通向字符流的橋樑:它使用指定的 charset 讀取字節並將其解碼爲字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺默認的字符集。
|—FileReader:用來讀取字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩衝區大小都是適當的。要自己指定這些值,可以先在 FileInputStream 上構造一個 InputStreamReader。
|—CharArrayReader
|—StringReader

Writer:寫入字符流的抽象類。子類必須實現的方法僅有 write(char[], int, int)、flush() 和 close()。
|—BufferedWriter:將文本寫入字符輸出流,緩衝各個字符,從而提供單個字符、數組和字符串的高效寫入。
|—OutputStreamWriter:是字符流通向字節流的橋樑:可使用指定的 charset 將要寫入流中的字符編碼成字節。它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。
|—FileWriter:用來寫入字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩衝區大小都是可接受的。要自己指定這些值,可以先在 FileOutputStream 上構造一個 OutputStreamWriter。
|—PrintWriter:
|—CharArrayWriter:
|—StringWriter:

字節流:

InputStream:是表示字節輸入流的所有類的超類。
|— FileInputStream:從文件系統中的某個文件中獲得輸入字節。哪些文件可用取決於主機環境。FileInputStream 用於讀取諸如圖像數據之類的原始字節流。要讀取字符流,請考慮使用 FileReader。
|— FilterInputStream:包含其他一些輸入流,它將這些流用作其基本數據源,它可以直接傳輸數據或提供一些額外的功能。
|— BufferedInputStream:該類實現緩衝的輸入流。
|— Stream:
|— ObjectInputStream:
|— PipedInputStream:

OutputStream:此抽象類是表示輸出字節流的所有類的超類。
|— FileOutputStream:文件輸出流是用於將數據寫入 File 或 FileDescriptor 的輸出流。
|— FilterOutputStream:此類是過濾輸出流的所有類的超類。
|— BufferedOutputStream:該類實現緩衝的輸出流。
|— PrintStream:
|— DataOutputStream:
|— ObjectOutputStream:
|— PipedOutputStream:

緩衝區

BufferedWriter:是給字符輸出流提高效率用的,那就意味着,緩衝區對象建立時,必須要先有流對象。明確要提高具體的流對象的效率。

FileWriter fw = new FileWriter("bufdemo.txt");
BufferedWriter bufw = new BufferedWriter(fw);//讓緩衝區和指定流相關聯。
for(int x=0; x<4; x++){
bufw.write(x+"abc");
bufw.newLine(); //寫入一個換行符,這個換行符可以依據平臺的不同寫入不同的換行符。
bufw.flush();//對緩衝區進行刷新,可以讓數據到目的地中。
}
bufw.close();//關閉緩衝區,其實就是在關閉具體的流。

BufferedReader:是給字符輸出流提高效率用的。

FileReader fr = new FileReader("bufdemo.txt");
BufferedReader bufr  = new BufferedReader(fr);
String line = null;
while((line=bufr.readLine())!=null){  //readLine方法返回的時候是不帶換行符的。
System.out.println(line);
}
bufr.close();

讀取鍵盤錄入

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//獲取鍵盤錄入
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));//輸出到控制檯
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
bufw.write(line.toUpperCase());//將輸入的字符轉成大寫字符輸出
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();

流對象:其實很簡單,就是讀取和寫入。但是因爲功能的不同,流的體系中提供N多的對象。那麼開始時,到底該用哪個對象更爲合適呢?這就需要明確流的操作規律。
流的操作規律:
1,明確源和目的。
數據源:就是需要讀取,可以使用兩個體系:InputStream、Reader;
數據匯:就是需要寫入,可以使用兩個體系:OutputStream、Writer;
2,操作的數據是否是純文本數據?
如果是:數據源:Reader
數據匯:Writer
如果不是:數據源:InputStream
數據匯:OutputStream
3,雖然確定了一個體系,但是該體系中有太多的對象,到底用哪個呢?
明確操作的數據設備。
數據源對應的設備:硬盤(File),內存(數組),鍵盤(System.in)
數據匯對應的設備:硬盤(File),內存(數組),控制檯(System.out)。
4,需要在基本操作上附加其他功能嗎?比如緩衝。
如果需要就進行裝飾。
轉換流特有功能:轉換流可以將字節轉成字符,原因在於,將獲取到的字節通過查編碼表獲取到指定對應字符。
轉換流的最強功能就是基於 字節流 + 編碼表 。沒有轉換,沒有字符流。
發現轉換流有一個子類就是操作文件的字符流對象:
InputStreamReader
|–FileReader
OutputStreamWriter
|–FileWrier
想要操作文本文件,必須要進行編碼轉換,而編碼轉換動作轉換流都完成了。所以操作文件的流對象只要繼承自轉換流就可以讀取一個字符了。
但是子類有一個侷限性,就是子類中使用的編碼是固定的,是本機默認的編碼表,對於簡體中文版的系統默認碼錶是GBK。

FileReader fr = new FileReader("a.txt");
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");
以上兩句代碼功能一致,
如果僅僅使用平臺默認碼錶,就使用FileReader fr = new FileReader("a.txt"); //因爲簡化。

如果需要制定碼錶,必須用轉換流。
轉換流 = 字節流+編碼表。
轉換流的子類File = 字節流 + 默認編碼表。
凡是操作設備上的文本數據,涉及編碼轉換,必須使用轉換流。

發佈了30 篇原創文章 · 獲贊 6 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章