【一】基于字節(jié)的輸入流

值得注意的地方有:
①Level 2的輸入流,大多數(shù)都會指明數(shù)據(jù)源的形式:例如ByteArray,File,Piped
②Level 3的輸入流,則不會出現(xiàn)具體的數(shù)據(jù)源名字,而是以功能取代:例如Buffered,LineNumber
所以說Level 3的輸入流是對Level 2輸入流的“封裝和過濾”。實(shí)際上Level 2的輸入流,都繼承于一個叫做:FilterInputStream的輸入流。
下面是對各個input stream的簡介:
①ByteArrayInputStream
從內(nèi)存中每次讀取一個字節(jié)的數(shù)據(jù),然后保存到內(nèi)置的緩沖區(qū)中。維持一個計(jì)數(shù)器用來記錄從數(shù)據(jù)源中讀入的字節(jié)數(shù)目。
調(diào)用該輸入流的close()方法不會產(chǎn)生任何實(shí)際的作用。因?yàn)樗?#8220;關(guān)閉”的對象是---內(nèi)存。而不是文件。不會拋出任何的IOException。
②FileInputStream
從文件系統(tǒng)中讀取原始的字節(jié)數(shù)據(jù)(raw bytes)。每次讀取一個字節(jié)
③PipedInputStream
管道輸入流,通常它的一端會和數(shù)據(jù)源連接,另一端和管道輸出流(PipedOutputStream) 連接。這樣從管輸入流讀入的任何數(shù)據(jù)將直接地傳輸?shù)焦艿垒敵隽鳌?br />
通常會有一個獨(dú)的線程從管道輸入流中讀取數(shù)據(jù),再交給另外一個線程,由另外的線程向管道輸出流中寫數(shù)據(jù)。如果使用單個線程進(jìn)行讀寫操作,很容易造成資源的死鎖。
④SequenceInputStream
把多個輸入流按順序合并成一個輸入流
⑤DataInputStream
從底層的其它字節(jié)輸入流中讀取字節(jié),然后轉(zhuǎn)換成與機(jī)器無關(guān)的原始類型數(shù)據(jù)(boolean,byte,char)
⑥BufferedInputStream
為底層的其它字節(jié)輸入流增加一個“緩沖”的功能,除此之外還可以“標(biāo)記”,“重置”輸入流。當(dāng)這個輸出流的對象被創(chuàng)建時,一個內(nèi)置的緩沖區(qū)也就被創(chuàng)建了。
隨著底層的輸入流的不斷讀入,緩沖區(qū)中的數(shù)據(jù)也在不同刷新。一次性地從底層的輸入流讀入多個字節(jié),方便后續(xù)的轉(zhuǎn)碼工作
【二】基于字節(jié)的輸出流

值得注意的是:
①在Level 2的輸出流,都是以功能來命名的。例如:Print,DataOutput,Buffered
②在Level 3的輸出流,則多數(shù)都是以數(shù)據(jù)源的形式來命名的。例如:ByteArray,File,Piped
所以說Level 2的輸出流必須依賴于Level 3的輸出流,實(shí)際上Level 2的輸出流,都繼承與一個叫做FilterOutputStream的輸出流
下面是對各個output stream的簡介:
①PrintStream
為底層的輸出流添加額外的功能,令到底層的輸出流可以方便地輸出各種經(jīng)過“格式化”的數(shù)據(jù)。和其它輸出流不同,該輸出流并不會拋出IOException,但是可以通過checkError方法來檢查是否有異常發(fā)生。
該輸出流具備自動flush功能,但寫完一個字節(jié)數(shù)組,或者碰到一個println方法的調(diào)用,或者當(dāng)要寫出的字符是換行符時。會自動清空flush。
默認(rèn)情況下所有要寫出的內(nèi)存字符,都會被該輸出流以平臺默認(rèn)編碼方式,轉(zhuǎn)換為字節(jié)流輸出
②DataOutputStream
允許應(yīng)用程序直接將基本類型數(shù)據(jù)(boolean, char, byte)直接寫出到底層的輸出流(內(nèi)部轉(zhuǎn)換為適當(dāng)?shù)淖止?jié))
③BufferedOutputStream
為底層的輸出流提供“緩沖”的功能,所有的寫出請求和要寫出的數(shù)據(jù)都會先緩沖到該輸出流的緩沖區(qū)中,在適當(dāng)?shù)臅r機(jī)一次性寫出。
注意該類的write方法被調(diào)用時并不一定立即將內(nèi)存中的數(shù)據(jù)寫出到數(shù)據(jù)源,而可能先將數(shù)據(jù)緩存起來。
④ByteArrayOutputStream
該輸出流能夠?qū)⒁獙懭雰?nèi)存的字節(jié),先緩存到自身的緩沖區(qū)中。并且該緩沖區(qū)的大小可以自動增長。如果要從該輸出流中提取字節(jié),可以使用toByteArray,如果要還原為字符串,可以使用toString。
關(guān)閉該輸出流并不會產(chǎn)生任何的IOException,因?yàn)樗妮敵龆耸?/span>---內(nèi)存而非文件。
⑤FileOutputStream
該輸出流以原始字節(jié)(raw bytes)的方式向底層文件系統(tǒng)中寫數(shù)據(jù)。在某些系統(tǒng)下,有時候只允許同一個文件
打開一個輸出流。所以如果該文件已經(jīng)被打開了,則再次打開一個輸出流會拋出異常。
【三】基于字符的輸入流
值得注意的地方有:
①Level 2的輸入流,大多數(shù)都會指明數(shù)據(jù)源的形式:例如CharArray,String,File
②Level 3的輸入流,則不會在出現(xiàn)具體的數(shù)據(jù)源名字,而是以功能取代:例如Buffered,LineNumber
但是和基于字節(jié)的輸入流結(jié)構(gòu)不同,FileInputStream是直接繼承于InputStream類的。但是FileReader卻是繼承與InputStreamReader的。而且BufferedReader不是繼承于FilterReader。看看下面的結(jié)構(gòu):
java.io.Reader (implements java.io.Closeable, java.lang.Readable)
java.io.BufferedReader
java.io.LineNumberReader
java.io.CharArrayReader
java.io.FilterReader
java.io.PushbackReader
java.io.InputStreamReader
java.io.FileReader
java.io.PipedReader
java.io.StringReader
這時為什么呢?其實(shí)如果我們知道InputStreamReader的作用是什么就知道了:它的作用是充當(dāng)一座基于字節(jié)流和字符流之間轉(zhuǎn)換的橋梁。它將從字節(jié)流讀取的字節(jié)按照編碼轉(zhuǎn)換成字符。
實(shí)際上任何對文件的IO讀寫,最終都是以字節(jié)的形式進(jìn)行的。所以讀取”字符”只不過是一種邏輯上的說法,那么FileReader為什么繼承于InputStreamReader就可以理解了。
下面是對各個Reader的介紹:
①CharArrayReader
直接從內(nèi)存中以“字符”的形式讀取數(shù)據(jù)。每次讀取一個字符,存放到緩存區(qū)中。
②FileReader
從文本文件中讀取字符的字符輸入流,該字符輸入流使用系統(tǒng)默認(rèn)的字符集編碼和緩存區(qū)大小,不能更改。如果需要重新調(diào)整輸入流的編碼,必須使用InputStreamReader。
③StringReader
從一個字符串中讀取內(nèi)容
④BufferedReader
為其它的基于字符的輸入流提供緩沖功能以提高效率。通常情況下,對于底層輸入流的任何一次read或者readLine請求都將導(dǎo)致直接的磁盤訪問,這將導(dǎo)致效率非常地下。
當(dāng)使用緩存的字符輸入流時,讀取請求將被緩存,在合適的時候一次性讀入批量數(shù)據(jù),再進(jìn)行編碼轉(zhuǎn)換。以此顯著提高效率。這個緩存輸入流的緩沖區(qū)大小是可以指定的。
⑤LineNumberReader
可以跟蹤讀入的“行數(shù)據(jù)”的字符輸入流。該輸入流內(nèi)置一個指示器,用于跟蹤讀入的數(shù)據(jù)的行數(shù)。默認(rèn)情況下行號從0開始。用戶可以通過setLineNumber和getLineNumber來設(shè)置/或者行號。一個行可以由“換行符”,“回車符”,“回車換行符”標(biāo)識。當(dāng)遇到其中任意一個符號時,指示器的值將增加1。
注意的是:setLineNumber方法并不會真正地改變數(shù)據(jù)在文件中的物理位置,而是簡單地修改了指示器的數(shù)值而已。
【四】基于字符的輸出流

值得注意的是:
①在Level 2的輸出流,都是以功能來命名的。例如:Print,Buffered
②在Level 3的輸出流,則多數(shù)都是以數(shù)據(jù)源的形式來命名的。例如:CharArray,File,String
所以說Level 2的輸出流必須依賴于Level 3的輸出流,實(shí)際上Level 2的輸出流,都繼承與一個叫做FilterWriter的輸出流
①PrintWriter
將對象數(shù)據(jù)以恰當(dāng)?shù)母袷捷敵龅轿谋据敵隽鳎?/span>PrintOutputStream類不同,后者當(dāng)碰到換行符的時候會清空緩沖區(qū)。但是PrintWriter不會,它只在print方法被調(diào)用時才會清空緩存。所以理論上來說它要比PrintOutputStream更加高效,因?yàn)橹灰彌_區(qū)允許,它可以接納更多的內(nèi)容而一次性寫入到文件。
這個類使用系統(tǒng)默認(rèn)的行分割符來代替“換行符"n”,因?yàn)椴皇撬械南到y(tǒng)都是通過“"n”來換行的。
②BufferedWriter
為其它字符輸出流提供緩沖功能,該輸出流的緩沖區(qū)大小可以設(shè)置,否則將使用默認(rèn)的緩沖區(qū)大小。這個類有一個newLine方法,用于返回一個基于系統(tǒng)的行分割符,而非一定是“"n”。這個類會緩存寫請求,當(dāng)要寫出的字符達(dá)到一定程度時就一次性地寫出到底層的文件輸出流。
③CharArrayWriter
類似于ByteArrayOutputStream,向內(nèi)存中寫字符。其中內(nèi)置一個緩沖區(qū),大小可以動態(tài)增長。如果要得到寫入的字符可以使用toCharArray方法,如果要構(gòu)造出字符串則可以使用toString方法。
④FileWriter
以基于字符的方式向文件中寫數(shù)據(jù)。該輸出流使用系統(tǒng)平臺默認(rèn)的字符集編碼方式和緩存區(qū)大小,不能設(shè)置改變。如果需要的話可以使用OutputStreamWriter。
某些系統(tǒng)只允許同一時刻一個文件被一個輸出流打開,所以假如文件已經(jīng)被另外的輸出流打開了,那么新的輸出流試圖打開同一個文件時將拋出異常。
【五】字節(jié)流和字符流之間的轉(zhuǎn)換

①InputStreamReader:
將字節(jié)流--》字符流,默認(rèn)使用系統(tǒng)編碼,可另外指定編碼方式。是一個解碼過程
new BufferedReader(new InputStreamReader(System.in))
②OutputStreamWriter:
將字符流--》字節(jié)流,默認(rèn)使用系統(tǒng)編碼,可另外指定編碼方式。是一個編碼過程
new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out));
-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
posted on 2010-03-02 09:47
Paul Lin 閱讀(4331)
評論(3) 編輯 收藏 所屬分類:
J2SE