作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!
計算機最重要的功能是處理資料。一個有用的計算機語言需要擁有良好的IO功能,以便讓未處理的資料流入程式,讓已處理的資料流出。
與其他語言相比,Java的IO功能顯得複雜。在其他語言中,許多IO功能(比如讀取檔案),是被封裝好的,可以用一兩行程式實作。在Java中,程式員往往需要多個層次的裝飾(decoration),才能實作檔案讀取。
相對的複雜性帶來的好處是IO的靈活性。在Java中,程式員可以控制IO的整個流程,進而設計出最好的IO方式。我們将在下文看到更多。
下面是我用于示範的檔案file.txt
我們先來研究一個檔案讀取的例子:
程式IO的關鍵在于建立BufferedReader對象br:
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
在建立的過程中,我們先建立了一個FileReader對象,這個對象的功能是從檔案"file.txt"中讀取位元組(byte)流,并轉換為文本流。在Java中,标準的文本編碼方式為unicode。BufferedReader()接收該FileReader對象,并拓展FileReader的功能,建立出一個BufferedReader對象。該對象除了有上述的檔案讀取和轉換的功能外,還提供了緩存讀取(buffered)的功能。最後,我們通過對br對象調用readLine()方法,可以逐行的讀取檔案。
(緩存讀取是在記憶體中開辟一片區域作為緩存,該區域存放FileReader讀出的文本流。當該緩存的内容被讀走後(比如readLine()指令),緩存會加載後續的文本流。)
BufferedReader()是一個裝飾器(decorator),它接收一個原始的對象,并傳回一個經過裝飾的、功能更複雜的對象。修飾器的好處是,它可以用于修飾不同的對象。我們這裡被修飾的是從檔案中讀取的文本流。其他的文本流,比如标準輸入,網絡傳輸的流等等,都可以被BufferedReader()修飾,進而實作緩存讀取。
下圖顯示了br的工作方式,資料自下而上流動:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuI2MmZTNiJWM0QmY0IjY2EjYyITYzMTMilTYzEDNiNGMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
事實上,Java提供了豐富的裝飾器。FileReader中合并了讀取和轉換兩個步驟,并采用了常用的預設設定,比如編碼采取unicode。我們可以使用FileInputStream + InputStreamReader的組合來替代FileReader,進而分離讀取位元組和轉換兩個步驟,并對兩個過程有更好的控制。
(當然,FileReader的使用更加友善。InputStreamReader是将FileInputStream轉換成一個Reader,用于處理unicode文本)
箭頭表示資料流動方向
流的讀寫來自于四個基類: InputStream, OutputStream, Reader和Writer。InputStream和Reader是處理讀取操作,OutputStream和Writer是處理寫入操作。它們都位于java.io包中。繼承關系如下:
java.io
此外,IOException有如下衍生類:
IOException
Reader和Writer及其衍生類是處理unicode文本。如我們看到的Buffered Reader, InputStreamReader或者FileReader。
InputStream和OutputStream及其衍生類是處理位元組(byte)流。計算機中的資料都可以認為是位元組形式,是以InputStream和OutputStream可用于處理更加廣泛的資料。比如我們可以使用下面的組合來讀取壓縮檔案中包含的資料(比如整數):
我們從壓縮檔案中讀出位元組流,然後解壓縮,最終讀出資料。
寫入(write)操作與讀取操作相似。我們可以通過使用裝飾,實作複雜的寫入功能。這裡是一個簡單的寫入文本的例子:
上面建立了file對象,用于處理檔案路徑。
這裡隻是對Java IO的基本介紹。Java的IO相對比較複雜。Java程式員需要花一些時間來熟悉java.io中的類及其功能。