標籤:大小 代碼 tin file 數組 nbsp 多個 better class
Java IO 是 Java 的一套 API, 用於讀入和寫出資料(輸入和輸出)。Java IO API 位於 java.io package。實際上 java.io package 沒有解決所有的輸入輸出情況,例如,web 頁面沒有包含在 Java IO package 裡面,而是由 Java 企業版本的 servlet 和 HTTP package 處理。
Java IO package 關注檔案、網路流(Network Stream), 記憶體緩衝區(internal memory buffer)的輸入輸出。Java IO package 沒有包含用於開啟網路通訊端(Network socket) 的類。網路通訊端由 Java Network API 開啟,然後 Java IO 的 InputStream / OutputStream 從開啟的通訊端讀入,或者向開啟的通訊端寫出資料。
Java NIO 用於處理非阻塞的輸入輸出操作。
Input 和 Output
最常見的資料來源或目的地有:
檔案
管道
網路連接
記憶體緩衝區
System.in, System.out, System.error
本質的資料流動請求如下
Source -> Program -> Destination
Stream
Stream 是 Java IO 的核心概念。Stream 是一個無盡頭的資料流,可以從一個 Stream 讀取資料,也可以向一個 Stream 寫入資料。Stream 沒有下標,也不能向前向後地移動,和數組不一樣。
Stream 可以簡單分為基於位元組(byte based),或者基於字元(character based)。
基於位元組的 stream 一般叫做 xxxxxxStream,例如 InputStream, OutputStream。這些 stream 一次唯讀入或寫出一個位元組,除了 DataInputStream / DataOutputStream。DataInputStream / DataOutputStream 用於處理 int / long / boolean 等類型。
基於字元的 stream 一般叫做 xxxxxxReader 或 xxxxxxWriter。
程式通過 InputStream 或者 Reader 讀入資料,通過 OutputStream 或者 Writer 寫出資料。
Source -> InputStream / Reader -> Program
Program -> OutputStream / Writer -> Destination
如果需要寫組件用於輸入或輸出,盡量讓組件依賴於 InputStream / OutputSteam,而不是他們的具體子類,使得代碼更加靈活應變。例如
InputStream is = new FileInputStream(filepath);
OutputSteam os = new FileOutputStream(filepath);
一次從檔案讀取一個位元組是非常慢的,使用 BufferedInputStream 一次讀取一大塊資料會快很多。例子
InputStream is = new BufferedInputStream(new FileInputStream("/Users/.../a.txt"));
緩衝(buffer) 也適用於 OutputStream,用於批量寫出到硬碟。
| |
Byte Based |
Character Based |
|
| |
Input |
Output |
Input |
Output |
comment |
| Basic |
InputStream |
OutputStream |
Reader InputStreamReader |
Writer OutputStreamWriter |
|
| Arrays |
|
|
|
|
|
| Files |
FileInputStream |
FileOutputStream |
FileReader |
FileWriter |
|
| Pipes |
|
|
|
|
|
| Buffering |
BufferedInputStream |
BufferedOutputStream |
|
|
In memory, better performance |
| Filter |
|
|
|
|
|
| Parsing |
PushbackInpustream |
|
PushbackReader |
|
|
| String |
|
|
|
|
|
| Data |
|
|
|
|
|
| Data-formated |
|
|
|
|
|
| Object |
|
|
|
|
|
| Utilities |
|
|
|
|
|
InputStream 和 OutputStream
InputStream 是 Java IO API 中所有 input stream 的基礎類。InputSream 下面的子類有 FileInputStream, BufferedInputStream。 InputStream 例子
InputStream is = new FileInputStream("/Users/.../a.txt"); int data = is.read(); while(data != -1){ System.out.print((char)data); data = is.read(); }
FileInputStream 是 InputStream 的子類。例子中省略了異常的處理。
當 read() 方法返回 -1 時,說明 stream 以及沒有內容可以讀取了。-1 是 int 值,而不是 byte 或 short 值。
read(byte[]) 方法一次讀取位元組數組,返回讀入的位元組數。read(byte[]) 比一次唯讀取一個位元組的 read() 要快。每次都需要檢查 read(byte[]) 的傳回值,來瞭解讀取的資料大小。
mark() 和 reset() 方法主要用於實現解譯器,用到情況小。
OutputStream 是 Java IO API 中所有 output stream 的基礎類。OutputStream 下面的子類有 FileOutputStream, BufferedOutputStrea。OutputStream 例子
OutputStream os = new FileOutputStream("/Users/.../b.txt"); byte[] b = {‘h‘, ‘e‘, ‘l‘, ‘l‘}; os.write(b); os.close();
write(byte[]) 方法將 byte 數組中的所有位元組寫入到 OutputStream 中
flush() 方法,將已經寫出 OutputSteam 的資料清刷(寫出)到底層的資料目的地。例如,如果 OutputStream 是 FileOutputStream,寫出到 FileOutputStream 的位元組還沒有全部寫出到硬碟。即使 java 代碼已經將資料寫出到 FileOutputStream,資料可能還在緩衝區而已。通過 flush() 方法,可以確保資料都清刷到硬碟(或網路)。
close() 方法,用於關閉 stream。通常位於 final 代碼塊。
Reader 和 Writer
Reader 和 Writer 在 Java IO 中的功能類似於 InputStream 和 OutputStream,差異點在於 Reader 和 Writer 基於字元。
Reader 是 Java IO API 中又有 reader 的基礎類。Reader 下面的子類有 BufferedReader, InputStreamReader, StringReader。例子
Reader reader = new FileReader("/Users/.../a.txt"); int data = reader.read(); while(data != -1){ System.out.print((char)data); data = reader.read(); }
InputStream 一次返回 8 bit( 一個 byte ) 的值 (0 到 255)
Reader 一次返回 16 bit 的值 ( 0 到 65535), 可能是一個或多個 byte,取決於文本採用的編碼格式。
Reader 可以套在 InputStream 外面,來讀取字元。
InputStream is = new FileInputStream("/Users/.../a.txt"); Reader rd = new InputStreamReader(is);
Writer 可以類似地套在 OutputStream 外面,寫出字元。
OutputStream os = new FileOutputStream("/Users/.../b.txt"); Writer wt = new OutputStreamWriter(os); wt.write("qqq"); wt.close();
Reader / Writer 子類的的組裝
Reader reader = new BufferedReader(new FileReader("/Users/.../a.txt")); Writer writer = new BufferedWriter(new FileWriter("/Users/.../c.txt"));
參考資料
Java IO Tutorial, jenkov
[Java] Java IO