天天看點

JAVA IO流詳解

一、流的概念和作用。

流是一種有順序的,有起點和終點的位元組集合,是對資料傳輸的總成或抽象。即資料在兩裝置之間的傳輸稱之為流,流的本質是資料傳輸,根據資料傳輸的特性講流抽象為各種類,友善更直覺的進行資料操作。

二、io流的分類。

根據資料處理類的不同分為:字元流和位元組流。

根據資料流向不同分為:輸入流和輸出流。

三、字元流和位元組流。

字元流的由來:因為資料編碼的不同,而有了對字元進行高效操作的流對象,其本質就是基于位元組流讀取時,去查了指定的碼表。字元流和位元組流的差別:

(1)讀寫機關不同:位元組流一位元組(8bit)為機關,字元流以字元為機關,根據碼表映射字元,一次可能讀多個位元組。

(2)處理對象不同:位元組流能處理所有類型的資料(例如圖檔,avi),而字元流隻能處理字元類型的資料。

(3)位元組流操作的時候本身是不會用到緩沖區的,是對檔案本身的直接操作。而字元流在操作的時候是會用到緩沖區的,通過緩沖區來操作檔案。

結論:優先使用位元組流,首先因為在硬碟上所有的檔案都是以位元組的形式進行傳輸或儲存的,包括圖檔等内容。但是字元流隻是在記憶體中才會形成,是以在開發中位元組流使用廣泛。

四、輸入流和輸出流。

對輸入流隻能進行讀操作,對輸出流隻能進行寫操作。程式中根據資料傳輸的不同特性使用不同的流。

五、輸入位元組流inputstream。

inputstream是所有輸入位元組流的父類,它是一個抽象類。

bytearrayinputstream、stringbufferinputstream、fileinputstream 是三種基本的媒體流,它們分别從byte 數組、stringbuffer、和本地檔案中讀取資料。pipedinputstream 是從與其它線程共用的管道中讀取資料,與piped 相關的知識後續單獨介紹。

objectinputstream 和所有filterinputstream的子類都是裝飾流(裝飾器模式的主角)。意思是fileinputstream類可以通過一個string路徑名建立一個對象,fileinputstream(string name)。而datainputstream必須裝飾一個類才能傳回一個對象,datainputstream(inputstream in)。

講解demo。

讀取檔案,節省空間。

逐一位元組讀:

注意:上面的幾個例子都是在知道檔案的内容多大,然後才展開的,有時候我們不知道檔案有多大,這種情況下,我們需要判斷是否獨到檔案的末尾。

位元組流讀取檔案:

注意:當讀到檔案末尾的時候會傳回-1.正常情況下是不會傳回-1的。

pushbackinputstream回退流操作:

六、輸出位元組流outputstream。

outputstream是所有輸出流的父類,它是一個抽象類。

bytearrayoutputstream、fileoutputstream是兩種基本的媒體流,它們分别向byte 數組、和本地檔案中寫入資料。pipedoutputstream 是向與其它線程共用的管道中寫入資料,

objectoutputstream 和所有filteroutputstream的子類都是裝飾流。具體例子跟inputstream是對應的。

執行個體demo:

向檔案中寫入字元串:

dataoutputstream類示例

java.util.zip.zipoutputstream

【案例】zipoutputstream類壓縮多個檔案

【案例】zipfile類展示

【案例】解壓縮檔案(壓縮檔案中隻有一個檔案的情況)

【案例】zipinputstream類解壓縮一個壓縮檔案中包含多個檔案的情況

七.幾個特殊的輸入流類分析

linenumberinputstream

主要完成從流中讀取資料時,會得到相應的行号,至于什麼時候分行、在哪裡分行是由改類主動确定的,并不是在原始中有這樣一個行号。在輸出部分沒有對應的部分,我們完全可以自己建立一個linenumberoutputstream,在最初寫入時會有一個基準的行号,以後每次遇到換行時會在下一行添加一個行号,看起來也是可以的。好像更不入流了。

pushbackinputstream

其功能是檢視最後一個位元組,不滿意就放入緩沖區。主要用在編譯器的文法、詞法分析部分。輸出部分的bufferedoutputstream 幾乎實作相近的功能。

stringbufferinputstream

已經被deprecated,本身就不應該出現在inputstream部分,主要因為string 應該屬于字元流的範圍。已經被廢棄了,當然輸出部分也沒有必要需要它了!還允許它存在隻是為了保持版本的向下相容而已。

sequenceinputstream

可以認為是一個工具類,将兩個或者多個輸入流當成一個輸入流依次讀取。完全可以從io 包中去除,還完全不影響io 包的結構,卻讓其更“純潔”――純潔的decorator 模式。

【案例】将兩個文本檔案合并為另外一個文本檔案

printstream

也可以認為是一個輔助工具。主要可以向其他輸出流,或者fileinputstream 寫入資料,本身内部實作還是帶緩沖的。本質上是對其它流的綜合運用的一個工具而已。一樣可以踢出io 包!system.err和system.out 就是printstream 的執行個體!

【案例】使用printstream進行格式化輸出

【案例】使用outputstream向螢幕上輸出内容

【案例】輸入輸出重定向

【案例】system.in重定向

八.字元輸入流reader

定義和說明:

在上面的繼承關系圖中可以看出:

reader 是所有的輸入字元流的父類,它是一個抽象類。

charreader、stringreader是兩種基本的媒體流,它們分别将char 數組、string中讀取資料。pipedreader 是從與其它線程共用的管道中讀取資料。

bufferedreader 很明顯就是一個裝飾器,它和其子類負責裝飾其它reader 對象。

filterreader 是所有自定義具體裝飾流的父類,其子類pushbackreader 對reader 對象進行裝飾,會增加一個行号。

inputstreamreader 是一個連接配接位元組流和字元流的橋梁,它将位元組流轉變為字元流。filereader可以說是一個達到此功能、常用的工具類,在其源代碼中明顯使用了将fileinputstream 轉變為reader 的方法。我們可以從這個類中得到一定的技巧。reader 中各個類的用途和使用方法基本和inputstream 中的類使用一緻。後面會有reader 與inputstream 的對應關系。

【案例】以循環方式從檔案中讀取内容

【案例】bufferedreader的小例子

注意:bufferedreader隻能接受字元流的緩沖區,因為每一個中文需要占據兩個位元組,是以需要将system.in這個位元組輸入流變為字元輸入流,采用:

bufferedreader buf = new bufferedreader(newinputstreamreader(system.in));

下面是一個執行個體:

【案例】scanner類從檔案中讀出内容

九.字元輸出流writer

在上面的關系圖中可以看出:

writer 是所有的輸出字元流的父類,它是一個抽象類。

chararraywriter、stringwriter 是兩種基本的媒體流,它們分别向char 數組、string 中寫入資料。

pipedwriter 是向與其它線程共用的管道中寫入資料,

bufferedwriter 是一個裝飾器為writer 提供緩沖功能。

printwriter 和printstream 極其類似,功能和使用也非常相似。

outputstreamwriter 是outputstream 到writer 轉換的橋梁,它的子類filewriter 其實就是一個實作此功能的具體類(具體可以研究一sourcecode)。功能和使用和outputstream 極其類似,後面會有它們的對應圖。

執行個體操作示範:

【案例】向檔案中寫入資料

注意:這個例子上之前的例子沒什麼差別,隻是你可以直接輸入字元串,而不需要你将字元串轉化為位元組數組。當你如果想問檔案中追加内容的時候,可以使用将上面的聲明out的哪一行換為:

writer out =new filewriter(f,true);

這樣,當你運作程式的時候,會發現檔案内容變為:hellohello如果想在檔案中換行的話,需要使用“\r\n”比如将str變為string str="\r\nhello";這樣檔案追加的str的内容就會換行了。

十.字元流與位元組流轉換

轉換流的特點:

(1)其是字元流和位元組流之間的橋梁

(2)可對讀取到的位元組資料經過指定編碼轉換成字元

(3)可對讀取到的字元資料經過指定編碼轉換成位元組

何時使用轉換流?

當位元組和字元之間有轉換動作時;

流操作的資料需要編碼或解碼時。

具體的對象展現:

inputstreamreader:位元組到字元的橋梁

outputstreamwriter:字元到位元組的橋梁

這兩個流對象是字元體系中的成員,它們有轉換作用,本身又是字元流,是以在構造的時候需要傳入位元組流對象進來。

位元組流和字元流轉換執行個體:

【案例】将位元組輸出流轉化為字元輸出流

【案例】将位元組輸入流轉換為字元輸入流

十一.file類

file類是對檔案系統中檔案以及檔案夾進行封裝的對象,可以通過對象的思想來操作檔案和檔案夾。 file類儲存檔案或目錄的各種中繼資料資訊,包括檔案名、檔案長度、最後修改時間、是否可讀、擷取目前檔案的路徑名,判斷指定檔案是否存在、獲得目前目錄中的檔案清單,建立、删除檔案和目錄等方法。

【案例 】建立一個檔案

【案例2】file類的兩個常量

此處多說幾句:有些同學可能認為,我直接在windows下使用\進行分割不行嗎?當然是可以的。但是在linux下就不是\了。是以,要想使得我們的代碼跨平台,更加健壯,是以,大家都采用這兩個常量吧,其實也多寫不了幾行。

【案例3】file類中的常量改寫案例1的代碼:

【案例4】删除一個檔案(或者檔案夾)

【案例5】建立一個檔案夾

【案例6】列出目錄下的所有檔案

【案例7】遞歸搜尋指定目錄的全部内容,包括檔案和檔案夾