按流的方向分:輸入流和輸出流。
按處理數據單位分:字節流和字符流。
按實現功能分:節點流和處理流。
輸出流:
輸入流:
字節流:一次讀入或讀出是8位二進制。
字符流:一次讀入或讀出是16位二進制。
字節流和字符流的原理是相同的,只不過處理的單位不同而已。后綴是Stream是字節流,而后綴是Reader,Writer是字符流。
字節流:處理字節數據的流對象。設備上的數據無論是圖片或者dvd,文字,它們都以二進制存儲的。二進制的最終都是以一個8位為數據單元進行體現,所以計算機中的最小數據單元就是字節。意味著,字節流可以處理設備上的所有數據,所以字節流一樣可以處理字符數據。
節點流:直接與數據源相連,讀入或讀出。
直接使用節點流,讀寫不方便,為了更快的讀寫文件,才有了處理流。
處理流:與節點流一塊使用,在節點流的基礎上,再套接一層,套接在節點流上的就是處理流。
下面是JavaIO流的結構示意圖:
字符流:
Reader:用于讀取字符流的抽象類。
|---BufferedReader:從字符輸入流中讀取文本,緩沖各個字符,從而實現字符、數組和行的高效讀取。 可以指定緩沖區的大小,或者可使用默認的大小。大 多數情況下,默認值就足夠大了。
|---LineNumberReader:跟蹤行號的緩沖字符輸入流。此類定義了方法setLineNumber(int)和getLineNumbner(),它們可分別用于設置和獲取當前行號。
|---InputStreamReader:是字節流通向字符流的橋梁:它使用指定的 charset 讀取字節并將其解碼為字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺默認的字符集。
|---FileReader:用來讀取字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩沖區大小都是適當的。要自己指定這些值,可以先在 FileInputStream 上構造一個 InputStreamReader。
***************************************************************************
Writer:寫入字符流的抽象類。
|---BufferedWriter:將文本寫入字符輸出流,緩沖各個字符,從而提供單個字符、數組和字符串的高效寫入。
|---OutputStreamWriter:是字符流通向字節流的橋梁:可使用指定的 charset 將要寫入流中的字符編碼成字節。它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。
|---FileWriter:用來寫入字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩沖區大小都是可接受的。要自己指定這些值,可以先在 FileOutputStream 上構造一個 OutputStreamWriter。
****************************************************************************
字節流:
InputStream:是表示字節輸入流的所有類的超類。
|--- FileInputStream:從文件系統中的某個文件中獲得輸入字節。哪些文件可用取決于主機環境。FileInputStream 用于讀取諸如圖像數據之類的原始字節流。要讀取字符流,請考慮使用 FileReader。
|--- FilterInputStream:包含其他一些輸入流,它將這些流用作其基本數據源,它可以直接傳輸數據或提供一些額外的功能。
|--- BufferedInputStream:該類實現緩沖的輸入流。
**************************************************************************
OutputStream:此抽象類是表示輸出字節流的所有類的超類。
|--- FileOutputStream:文件輸出流是用于將數據寫入 File 或 FileDescriptor 的輸出流。
|--- FilterOutputStream:此類是過濾輸出流的所有類的超類。
|--- BufferedOutputStream:該類實現緩沖的輸出流。
流的操作規律:
1、明確源和目的。
數據源:就是需要讀取,可以使用兩個體系:InputStream、Reader;
數據匯:就是需要寫入,可以使用兩個體系:OutputStream、Writer;
2、操作的數據是否是純文本數據?
如果是:數據源:Reader
數據匯:Writer
如果不是:數據源:InputStream
數據匯:OutputStream
3、雖然確定了一個體系,但是該體系中有太多的對象,到底用哪個呢?
明確操作的數據設備。
數據源對應的設備:硬盤(File),內存(數組),鍵盤(System.in)
數據匯對應的設備:硬盤(File),內存(數組),控制臺(System.out)。
4、需要在基本操作上附加其他功能嗎?比如緩沖。
如果需要就進行裝飾。
/記住,只要一讀取鍵盤錄入,就用這句話。BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
1.輸入字節流InputStreamIO 中輸入字節流的繼承圖可見上圖,可以看出:
InputStream 是所有的輸入字節流的父類,它是一個抽象類。ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三種基本的介質流,它們分別從Byte 數組、StringBuffer、和本地文件中讀取數據。PipedInputStream 是從與其它線程共用的管道中讀取數據,與Piped 相關的知識后續單獨介紹。ObjectInputStream 和所有FilterInputStream 的子類都是裝飾流(裝飾器模式的主角)。IO 中輸出字節流的繼承圖可見上圖,可以看出:
OutputStream 是所有的輸出字節流的父類,它是一個抽象類。ByteArrayOutputStream、FileOutputStream 是兩種基本的介質流,它們分別向Byte 數組、和本地文件中寫入數據。PipedOutputStream 是向與其它線程共用的管道中寫入數據,ObjectOutputStream 和所有FilterOutputStream 的子類都是裝飾流。
圖中藍色的為主要的對應部分,紅色的部分就是不對應部分。紫色的虛線部分代表這些流一般要搭配使用。從上面的圖中可以看出Java IO 中的字節流是極其對稱的?!按嬖诩昂侠怼蔽覀兛纯催@些字節流中不太對稱的幾個類吧!
LineNumberInputStream 主要完成從流中讀取數據時,會得到相應的行號,至于什么時候分行、在哪里分行是由改類主動確定的,并不是在原始中有這樣一個行號。在輸出部分沒有對應的部分,我們完全可以自己建立一個LineNumberOutputStream,在最初寫入時會有一個基準的行號,以后每次遇到換行時會在下一行添加一個行號,看起來也是可以的。好像更不入流了。PushbackInputStream 的功能是查看最后一個字節,不滿意就放入緩沖區。主要用在編譯器的語法、詞法分析部分。輸出部分的BufferedOutputStream 幾乎實現相近的功能。StringBufferInputStream 已經被DePRecated,本身就不應該出現在InputStream 部分,主要因為String 應該屬于字符流的范圍。已經被廢棄了,當然輸出部分也沒有必要需要它了!還允許它存在只是為了保持版本的向下兼容而已。SequenceInputStream 可以認為是一個工具類,將兩個或者多個輸入流當成一個輸入流依次讀取。完全可以從IO 包中去除,還完全不影響IO 包的結構,卻讓其更“純潔”――純潔的Decorator 模式。PrintStream 也可以認為是一個輔助工具。主要可以向其他輸出流,或者FileInputStream 寫入數據,本身內部實現還是帶緩沖的。本質上是對其它流的綜合運用的一個工具而已。一樣可以踢出IO 包!System.out 和System.out 就是PrintStream 的實例!在上面的繼承關系圖中可以看出:
Reader 是所有的輸入字符流的父類,它是一個抽象類。CharReader、StringReader 是兩種基本的介質流,它們分別將Char 數組、String中讀取數據。PipedReader 是從與其它線程共用的管道中讀取數據。BufferedReader 很明顯就是一個裝飾器,它和其子類負責裝飾其它Reader 對象。FilterReader 是所有自定義具體裝飾流的父類,其子類PushbackReader 對Reader 對象進行裝飾,會增加一個行號。InputStreamReader 是一個連接字節流和字符流的橋梁,它將字節流轉變為字符流。FileReader 可以說是一個達到此功能、常用的工具類,在其源代碼中明顯使用了將FileInputStream 轉變為Reader 的方法。我們可以從這個類中得到一定的技巧。Reader 中各個類的用途和使用方法基本和InputStream 中的類使用一致。后面會有Reader 與InputStream 的對應關系。在上面的關系圖中可以看出:
Writer 是所有的輸出字符流的父類,它是一個抽象類。CharArrayWriter、StringWriter 是兩種基本的介質流,它們分別向Char 數組、String 中寫入數據。PipedWriter 是向與其它線程共用的管道中寫入數據,BufferedWriter 是一個裝飾器為Writer 提供緩沖功能。PrintWriter 和PrintStream 極其類似,功能和使用也非常相似。OutputStreamWriter 是OutputStream 到Writer 轉換的橋梁,它的子類FileWriter 其實就是一個實現此功能的具體類(具體可以研究一SourceCode)。功能和使用和OutputStream 極其類似,后面會有它們的對應圖。
轉換流的特點:
其是字符流和字節流之間的橋梁可對讀取到的字節數據經過指定編碼轉換成字符可對讀取到的字符數據經過指定編碼轉換成字節何時使用轉換流?
當字節和字符之間有轉換動作時;流操作的數據需要編碼或解碼時。具體的對象體現:
InputStreamReader:字節到字符的橋梁OutputStreamWriter:字符到字節的橋梁這兩個流對象是字符體系中的成員,它們有轉換作用,本身又是字符流,所以在構造的時候需要傳入字節流對象進來。
File類是對文件系統中文件以及文件夾進行封裝的對象,可以通過對象的思想來操作文件和文件夾。 File類保存文件或目錄的各種元數據信息,包括文件名、文件長度、最后修改時間、是否可讀、獲取當前文件的路徑名,判斷指定文件是否存在、獲得當前目錄中的文件列表,創建、刪除文件和目錄等方法。
該對象并不是流體系中的一員,其封裝了字節流,同時還封裝了一個緩沖區(字符數組),通過內部的指針來操作字符數組中的數據。 該對象特點:
該對象只能操作文件,所以構造函數接收兩種類型的參數:a.字符串文件路徑;b.File對象。該對象既可以對文件進行讀操作,也能進行寫操作,在進行對象實例化時可指定操作模式(r,rw)注意:該對象在實例化時,如果要操作的文件不存在,會自動創建;如果文件存在,寫數據未指定位置,會從頭開始寫,即覆蓋原有的內容。 可以用于多線程下載或多個線程同時寫數據到文件
10、打印流(PrintStream/PrintWriter) PrintStream是一個字節打印流,System.out對應的類型就是PrintStream,它的構造函數可以接受三種數據類型的值:1.字符串路徑。2.File對象 3.OutputStream PrintStream是一個字符打印流,它的構造函數可以接受四種類型的值:1.字符串路徑。2.File對象 3.OutputStream 4.Writer 對于1、2類型的數據,可以指定編碼表,也就是字符集,對于3、4類型的數據,可以指定自動刷新,當該自動刷新為True時,只有3個方法可以用:println,printf,format。 11、對象流(ObjectInputStream/ObjectOutputStream) 該類型的流可以把類作為一個整體進行存取,主要方法有: Object readObject();該方法拋出異常:ClassNotFountException。 void writeObject(Object):被寫入的對象必須實現一個接口:Serializable,否則就會拋出:NotSerializableException新聞熱點
疑難解答