網頁

2009年12月20日 星期日

Java Stream 簡介

Java 的 stream 相關類別很多,讓人目不暇給,
FileInputStream, FileOutputStream, FileReader, FileWriter
光是 File 開頭的就有這四種,
其他開頭的還有 Object, Data, Print, Buffered....,
另外還有兩個 InputStreamReader 和 OutputStreamWriter 這兩個奇怪東西。


到底我該用的是什麼? 它們之間又有什麼差別?

先從 Reader/Writer 和 InputStream/OutputStream 說起好了,

Reader 是讀,InputStream 也是讀,
兩著乍看之下都是在做讀資料,
其間差別究竟何在?

根據 API 上的說法,InputStream 是以 byte 為單位,
而 Reader 則是以字元為單位,並且會根據編碼 decode。
當然,OutputStream 與 Writer 的差別也是同理。


再來討論這些 streams 的另一個差別,
在前面所提到的所有類別中,
只有 File 開頭類別的沒有 "以其它 Stream 類別為參數" 的 Constructor。
(以下就只以 OutputStream 為例)

這是因為只有 FileOutputStream 是直接在跟 File 溝通,
其他的 Stream 都只是將資料寫入 Constructor 參數中的 OutputStream。


那麼,我們為什麼不只用 FileOutputStream 就好?

你可以去看看 FileOutputStream 提供了哪些 method,
會發現它只提供了有關 byte array 的操作,
如果你想要輸出一行字給 FileOutputStream,你可能會自己處理得很辛苦。

所以啦,Java 提供了一系列好用的 Stream,
把最底層,只提供 byte array 操作的 Stream 包裝起來,
讓你操作起來更直覺,
因此想要寫入字串可以用 PrintStream,
想要把各種基本資料型態,
如 int, double...等的 "值" 輸出,可以用 DataOutputStream。
想要把整個物件 Serialize,則可以用 ObjectOutputStream。

或許你有注意到,
PrintWriter 也有提供檔名和 File 物件做為 Constructor 的參數呀!
但這只是為了你使用上的方便,
實際上 PrintWriter 還是會自己宣告一份 FileOutputStream 與檔案溝通。


而 InputStreamReader 和 OutputStreamWriter,
則是用來將 Stream 包裝成 Reader/Writer,
並且由這兩個物件做編碼的處理。


另外,這些包裝是可以多層的,
例如 ObjectOutputStream -> BufferedOutputStream -> FileOutputStream,
或著 PrintWriter -> OutputStreamWriter -> FileOutputStream。


如果你想要惡搞,
用 ObjectOutputStream 去包裝 DataOutputStream,
甚至是 ObjectOutputStream -> ObjectOutputStream -> ObjectOutputStream -> ....
這樣在宣告與執行上也不會有問題。
(這樣也算是錯誤,不過這是程式邏輯上的錯誤)

沒有留言:

張貼留言