JavaIo:JavaIo輸入輸出流

轉(zhuǎn)載至“http://segmentfault.com/a/1190000003817055?utm_source=Weibo&utm_medium=shareLink&utm_campaign=socialShare”

流的原理:

一連串有順序的數(shù)據(jù)系列可以看成是一個(gè)流。

輸入輸出流:


? ? ?數(shù)據(jù)從IO輸入到程序的流是輸入流,數(shù)據(jù)從程序輸出到IO的流是輸出流。

下面我們使用字節(jié)輸入輸出流來說明這個(gè)問題:

1.輸入流 InputStream一般是由javaio對(duì)象(如File)建立的,當(dāng)新建一個(gè)InputStream時(shí),io對(duì)象建立了一個(gè)包含有數(shù)據(jù)的管道(其實(shí)就是我們所說的這個(gè)“流”)并將io對(duì)象存儲(chǔ)的數(shù)據(jù)輸入(input)到管道中,因此管道里的數(shù)據(jù)流就是io對(duì)象內(nèi)的數(shù)據(jù)。當(dāng)調(diào)用InputStream數(shù)據(jù)流的read方法時(shí),管道里的數(shù)據(jù)流讀出到內(nèi)存對(duì)象中(比如數(shù)組或者字符串),注意,讀出的比特流將會(huì)被移除,具體能可讀的數(shù)據(jù)的量可用available函數(shù)來查看;

2.輸出流 OutputStream也是由javaio對(duì)象(如File)建立的,當(dāng)新建一個(gè)OutputStream時(shí),io對(duì)象建立了一個(gè)包含有數(shù)據(jù)流的管道并建立起io對(duì)象和管道的映射。 當(dāng)調(diào)用OutputStream數(shù)據(jù)流的write方法時(shí),內(nèi)存對(duì)象里的數(shù)據(jù)就會(huì)流入管道里,而管道里的數(shù)據(jù)流輸出(output)到io對(duì)象中,flush函數(shù)將促使數(shù)據(jù)緩沖區(qū)中的數(shù)據(jù)被寫入到io設(shè)備(文件本身)中區(qū);


在這個(gè)例子里我們可以充分看出輸入流創(chuàng)建和輸入的過程,首先創(chuàng)建一個(gè)File對(duì)象來映射IO上的這個(gè)文件,依據(jù)這個(gè)File對(duì)象來創(chuàng)建輸入流InputStream對(duì)象,注意,創(chuàng)建過后輸入流里按序存儲(chǔ)著IO文件里的數(shù)據(jù)內(nèi)容(這個(gè)過程中可能InputStream并不是其存儲(chǔ)作用的,因?yàn)槿艄@樣大文件內(nèi)的數(shù)據(jù)一次性存儲(chǔ)可能會(huì)爆內(nèi)存,所以這個(gè)過程應(yīng)該是InputStream映射到IO文件),調(diào)用輸入流InputStream對(duì)象的read方法,即可將流內(nèi)的數(shù)據(jù)輸入到程序中的之前創(chuàng)建的對(duì)象內(nèi),最終在使用完后關(guān)閉作為有限資源的輸入流。這個(gè)過程完成了數(shù)據(jù)由IO對(duì)象輸入到程序。

注意:如果是上次沒有讀完輸入流內(nèi)的內(nèi)容,那么下一次程序到InputStream去讀的時(shí)候是接著上次的結(jié)尾讀的,這個(gè)可以根據(jù)InputStream對(duì)象的available方法看出來,所以在這個(gè)角度來看輸入流就像是文件里的索引指針一樣。


在這個(gè)例子里我們可以充分看出輸出流創(chuàng)建和輸出的過程,首先創(chuàng)建一個(gè)File對(duì)象來映射IO上的這個(gè)文件,依據(jù)這個(gè)File對(duì)象來創(chuàng)建輸出流OutputStream對(duì)象,調(diào)用輸出流OutputStream對(duì)象的write方法,即可將程序?qū)ο笾械臄?shù)據(jù)寫到輸出流中然后從輸出流輸出到IO文件中去,最終在使用完后關(guān)閉作為有限資源的輸出流。這個(gè)過程完成了數(shù)據(jù)由程序輸出到IO文件中。

字符輸入輸出流的道理是一樣的,只不過字符流是直接處理字符的,而字節(jié)流的處理單位是字節(jié)。read和write的API大同小異,無非就是把流里面的內(nèi)容和緩沖區(qū)通過這些函數(shù)來進(jìn)行交換。

流的流:

既然可以依據(jù)IO文件來創(chuàng)建流在文件和程序之間交換數(shù)據(jù),那么我們可不可以從中間再加入一個(gè)流來作為中轉(zhuǎn)處理一下數(shù)據(jù)呢?這個(gè)流的流構(gòu)成的多流鏈稱之為“流對(duì)象鏈”,這個(gè)過程說明不是所有的流都是直接和原始數(shù)據(jù)源打交道的,所以有如下定義:

節(jié)點(diǎn)流(Node Stream)直接連接到數(shù)據(jù)源,直接從IO文件上輸入或輸出數(shù)據(jù);

處理流(Processing Stream)是對(duì)一個(gè)已存在的流的連接和封裝,通過所封裝的流的功能調(diào)用實(shí)現(xiàn)增強(qiáng)的數(shù) 據(jù)讀寫功能,它并不直接連到數(shù)據(jù)源。


這個(gè)過程的原理如下圖所示:

在這個(gè)例子里我們可以充分看出流對(duì)象鏈形成的過程,首先創(chuàng)建一個(gè)File對(duì)象來映射IO上的這個(gè)文件,依據(jù)這個(gè)File對(duì)象來創(chuàng)建輸出流OutputStream對(duì)象,利用這個(gè)輸出流對(duì)象再創(chuàng)建一個(gè)PrintStream對(duì)象來鏈接輸出流對(duì)象,調(diào)用PrintStream對(duì)象的print方法,即可將程序?qū)ο笾械臄?shù)據(jù)寫到PrintStream中然后再輸出到IO文件中去,最終在使用完后關(guān)閉作為有限資源的流。這個(gè)過程完成了數(shù)據(jù)由程序輸出到IO文件中。


流中的緩沖技術(shù)

在內(nèi)存中開辟一塊區(qū)域,稱為緩沖區(qū),當(dāng)緩沖區(qū)滿時(shí)一次寫入到磁盤中,提高了I/O的性能。和一般的輸入輸出流相比,這樣的帶有緩沖區(qū)的流可以做到更好的IO性能,在帶緩沖的輸出流時(shí)由于緩沖區(qū)的存在,需要在最后強(qiáng)制使用flush函數(shù)將緩沖區(qū)中剩余的內(nèi)容全部輸出到IO設(shè)備中去。


這里表現(xiàn)的是這個(gè)過程,IO文件里的數(shù)據(jù)經(jīng)過文件輸入流FileInputStream對(duì)象流入緩沖輸入流BufferedInputStream對(duì)象,之后所有的數(shù)據(jù)(在數(shù)據(jù)量較小的時(shí)候,一般是小于8K時(shí),后面會(huì)討論到)流入輸入流的緩沖區(qū),之后每次在讀取的時(shí)候都是直接從緩沖區(qū)讀到臨時(shí)的數(shù)組中去而不是再從流讀入,然后臨時(shí)數(shù)組的數(shù)據(jù)在write函數(shù)的作用下寫到輸出流的緩沖區(qū)中去,緩沖區(qū)滿后數(shù)據(jù)會(huì)經(jīng)由緩沖輸出流BufferedOutputStream對(duì)象流入文件輸出流FileOutputStream對(duì)象,并最終輸出到IO文件中去,如果緩沖區(qū)不滿的話是不會(huì)自發(fā)輸出到緩沖輸出流中去的,因此往往我們需要在最后緩沖區(qū)不滿的情況下強(qiáng)制執(zhí)行輸出流的flush方法讓緩沖區(qū)數(shù)據(jù)強(qiáng)制輸出到輸出流中去。這個(gè)過程完成了IO文件數(shù)據(jù)的流轉(zhuǎn),中間有一個(gè)緩沖區(qū)在暫存數(shù)據(jù)。


在這個(gè)例子里我們可以更容易地發(fā)現(xiàn)BufferedReader這樣的緩沖類輸入流的緩沖作用,當(dāng)首次調(diào)用readline(或者read等各種讀取方法)函數(shù)讀取這個(gè)輸入流的時(shí)候,就會(huì)將流里的數(shù)據(jù)讀進(jìn)程序?yàn)锽ufferedInputStream對(duì)象分配的一個(gè)緩沖區(qū)中,而在此后的讀取輸入流的過程中就不需要去流中讀取而只需要去緩沖區(qū)里讀取就可以了,將開銷較大的IO數(shù)據(jù)交換過程變成了開銷小得多的內(nèi)存數(shù)據(jù)交換,進(jìn)而提高了IO效率,這是緩沖輸入輸出流的好處。但是這個(gè)緩沖區(qū)的大小是有限的,jdk為這個(gè)大小確定的固定值為8K字節(jié),一旦超過這個(gè)值的話在第一次讀取時(shí)就只能緩沖最多8K子節(jié)的數(shù)據(jù),超出的部分只能在之后再緩沖。最后,如果要結(jié)束任務(wù)寫入輸出流的時(shí)候,要注意調(diào)用輸出流的flush方法來將緩沖區(qū)強(qiáng)制清空使之全部輸出到輸出流中去。


上面這個(gè)過程演示了緩沖區(qū)的大小,當(dāng)輸入流的內(nèi)容填不滿緩沖區(qū)時(shí)(也就是不足8192字節(jié)時(shí)),如果不用flush沒有辦法自動(dòng)寫入文件,當(dāng)原來緩沖區(qū)的大小大于這個(gè)值的時(shí)候,會(huì)一次性把上次的8192字節(jié)自動(dòng)寫入,下一次會(huì)再讀入8192個(gè)字節(jié),完成上面的過程。因此,這提醒我們,使用帶有緩沖的輸出流時(shí)務(wù)必要在最后強(qiáng)制清空緩沖進(jìn)入輸出流才能保證數(shù)據(jù)不出錯(cuò)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容