前言:
此文適合JAVA IO體系的朋友。
主題:
Java IO:即 Java 輸入 / 輸出系統。
Java 的輸入和輸出:讀數據就用輸入(InputStream/Reader), 寫數據就用輸出(OutputStream/Writer)。
Stream:Java 中將數據的輸入輸出抽象爲流,流是一組有順序的,單向的,有起點和終點的數據集合,就像水流。按照流中的最小數據單元又分爲字節流和字符流。
- 字節流:以 8 位(即 1 byte,8 bit)作爲一個數據單元,數據流中以【字節】爲最小數據單元。
- 字符流:以 16 位(即 1 char,2 byte,16 bit)作爲一個數據單元,數據流中以【字符】爲最小數據單元(Java 中的字符是 Unicode 編碼,一個字符佔用兩個字節)。
1.IO體系常用流類
2.IO分類
3.歸納總結
歸納前,先區分節點流和處理流。Java io又分爲節點流和處理流,節點流是真正直接處理數據的;處理流是裝飾加工節點流的。
節點流
- 文件流:FileInputStream,FileOutputStrean,FileReader,FileWriter,它們都會直接操作文件,直接與 OS 底層交互。因此他們被稱爲節點流 (使用這幾個流的對象之後,需要關閉流對象,因爲 java 垃圾回收器不會主動回收。不過在 Java7 之後,可以在 try() 括號中打開流,最後程序會自動關閉流對象,不再需要顯示地 close)
- 數組流:ByteArrayInputStream,ByteArrayOutputStream,CharArrayReader,CharArrayWriter,對數組進行處理的節點流。 字符串流:StringReader,StringWriter,其中 StringReader 能從 String 中讀取數據並保存到 char 數組
- 管道流:PipedInputStream,PipedOutputStream,PipedReader,PipedWrite,對管道進行處理的節點流。
處理流
處理流是對一個已存在的流的連接和封裝,通過所封裝的流的功能調用實現數據讀寫。如 BufferedReader。 處理流的構造方法總是要帶一個其他的流對象做參數。 常用處理流(通過關閉處理流裏面的節點流來關閉處理流)
- 緩衝流 :BufferedImputStrean,BufferedOutputStream,BufferedReader ,BufferedWriter,需要父類作爲參數構造,增加緩衝功能,避免頻繁讀寫硬盤,可以初始化緩衝數據的大小,由於帶了緩衝功能,所以就寫數據的時候需要使用 flush 方法,另外,BufferedReader 提供一個 readLine( ) 方法可以讀取一行,而 FileInputStream 和 FileReader 只能讀取一個字節或者一個字符,因此 BufferedReader 也被稱爲行讀取器。
- 轉換流:InputStreamReader,OutputStreamWriter,要 inputStream 或 OutputStream 作爲參數,實現從字節流到字符流的轉換,我們經常在讀取鍵盤輸入(System.in)或網絡通信的時候,需要使用這兩個類。
- 數據流:DataInputStream,DataOutputStream,提供將基礎數據類型寫入到文件中,或者讀取出來。
3.1字節輸入流
- InputStream 是所有的輸入字節流的父類,它是一個抽象類。
- PushbackInputStream、DataInputStream 和 BufferedInput Stream都是處理流,他們的的父類是 FilterInputStream。
- ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三種基本的介質流,它們分別從 Byte 數組、StringBuffer、和本地文件中讀取數據。PipedInputStream 是從與其它線程共用的管道中讀取數據。
3.2字節輸出流
- OutputStream 是所有的輸出字節流的父類,它是一個抽象類。
- ByteArrayOutputStream、FileOutputStream 是兩種基本的介質流,它們分別向 Byte 數組、和本地文件中寫入數據。
- PipedOutputStream 是向與其它線程共用的管道中寫入數據。
- BufferedOutputStream、DataOutputStream 和 PrintStream 都是處理流,他們的的父類是 FilterOutputStream。
3.3字符輸入流
- Reader 是所有的輸入字符流的父類,它是一個抽象類。
- CharReader、StringReader 是兩種基本的介質流,它們分別將 Char 數組、String 中讀取數據。PipedReader 是從與其它線程共用的管道中讀取數據。
- BufferedReader 很明顯就是一個裝飾器,它和其子類負責裝飾其它 Reader 對象。
- FilterReader 是所有自定義具體裝飾流的父類,其子類 PushbackReader 對 Reader 對象進行裝飾,會增加一個行號。
- InputStreamReader 是一個連接字節流和字符流的橋樑,它將字節流轉變爲字符流。
3.4字符輸入流
- Writer 是所有的輸出字符流的父類,它是一個抽象類。
- CharArrayWriter、StringWriter 是兩種基本的介質流,它們分別向 Char 數組、String 中寫入數據。PipedWriter 是向與其它線程共用的管道中寫入數據。
- BufferedWriter 是一個裝飾器爲 Writer 提供緩衝功能。
- PrintWriter 和 PrintStream 極其類似,功能和使用也非常相似。
- OutputStreamWriter 是 OutputStream 到 Writer 轉換的橋樑,它的子類 FileWriter 其實就是一個實現此功能的具體類。
4.JAVA IO 常見面試題
1、字節流和字符流的區別?
- 讀寫單位不同:字節流以字節(8 bit)爲單位,字符流以字符爲單位。
- 處理對象不同:字節流能處理所有類型的數據(如圖片、avi 等),而字符流只能處理字符類型的數據。
- 字節流沒有緩衝區,是直接輸出的,而字符流是輸出到緩衝區的。因此在輸出時,字節流不調用 colse() 方法時,信息已經輸出了,而字符流只有在調用 close() 方法關閉緩衝區時,信息才輸出。要想字符流在未關閉時輸出信息,則需要手動調用 flush() 方法。
2、什麼叫對象序列化,什麼是反序列化,實現對象序列化需要做哪些工作?
- 對象序列化:將對象以二進制的形式保存在硬盤上;
- 反序列化:將二進制的文件轉化爲對象讀取;
- 實現 serializable 接口可以實現對象序列化,其中沒有需要實現的方法,implements Serializable 只是爲了標註該對象是可被序列化的。
例如,在 web 開發中,如果對象被保存在了 Session 中,tomcat 在重啓時要把 Session 對象序列化到硬盤,這個對象就必須實現 Serializable 接口。如果對象要經過分佈式系統進行網絡傳輸,被傳輸的對象就必須實現 Serializable 接口。
3、什麼是 Filter 流有哪些?
FilterStream 是一種 IO 流,主要作用是用來對存在的流增加一些額外的功能,像給目標文件增加源文件中不存在的行數,或者增加拷貝的性能等。在 java.io 包中主要由 4 個可用的 filter Stream。兩個字節 filter stream,兩個字符 filter stream。分別是:FilterInputStream,FilterOutputStream,FilterReader and FilterWriter. 這些類是抽象類,不能被實例化的。
FilterInputStream 流的子類:
- DataInputStream 可以把包括基本類型在內的數據和字符串按順序從數據源讀入,它有一些特殊的方法如 readInt(),readDouble() 和 readLine() 等可以讀取一個 int,double 和一個 string。
- BufferedInputStream 增加性能。
- PushbackInputStream 推送要求的字節到系統中。
- 注:其它子類見 Java io 分類圖。
4、說說 RandomAccessFile?
它在 java.io 包中是一個特殊的類,既不是輸入流也不是輸出流,它兩者都可以做到。他是 Object 的直接子類。通常來說,一個流只有一個功能,要麼讀,要麼寫。但是 RandomAccessFile 既可以讀文件,也可以寫文件。而且 RandomAccessFile 支持對文件的隨機訪問。