天天看點

java io流讀寫檔案換行_IO與檔案讀寫---Java的IO流架構

【一】基于位元組的輸入流

java io流讀寫檔案換行_IO與檔案讀寫---Java的IO流架構

值得注意的地方有:

① Level 2 的輸入流,大多數都會指明資料源的形式:例如 ByteArray , File , Piped

② Level 3 的輸入流,則不會出現具體的資料源名字,而是以功能取代:例如 Buffered , LineNumber

是以說 Level 3 的輸入流是對 Level 2 輸入流的“封裝和過濾”。實際上 Level 2 的輸入流,都繼承于一個叫做: FilterInputStream 的輸入流。

下面是對各個 input stream 的簡介:

① ByteArrayInputStream

從記憶體中每次讀取一個位元組的資料,然後儲存到内置的緩沖區中。維持一個計數器用來記錄從資料源中讀入的位元組數目。

調用該輸入流的 close() 方法不會産生任何實際的作用。因為它“關閉”的對象是 --- 記憶體。而不是檔案。不會抛出任何的 IOException 。

② FileInputStream

從檔案系統中讀取原始的位元組資料 (raw bytes) 。每次讀取一個位元組

③PipedInputStream 管道輸入流,通常它的一端會和資料源連接配接,另一端和管道輸出流(PipedOutputStream) 連接配接。這樣從管輸入流讀入的任何資料将直接地傳輸到管道輸出流。

通常會有一個獨的線程從管道輸入流中讀取資料,再交給另外一個線程,由另外的線程向管道輸出流中寫資料。如果使用單個線程進行讀寫操作,很容易造成資源的死鎖。 ④ SequenceInputStream

把多個輸入流按順序合并成一個輸入流

⑤ DataInputStream

從底層的其它位元組輸入流中讀取位元組,然後轉換成與機器無關的原始類型資料 (boolean , byte , char)

⑥ BufferedInputStream

為底層的其它位元組輸入流增加一個“緩沖”的功能,除此之外還可以“标記”,“重置”輸入流。當這個輸出流的對象被建立時,一個内置的緩沖區也就被建立了。

随着底層的輸入流的不斷讀入,緩沖區中的資料也在不同重新整理。一次性地從底層的輸入流讀入多個位元組,友善後續的轉碼工作

【二】基于位元組的輸出流

java io流讀寫檔案換行_IO與檔案讀寫---Java的IO流架構

值得注意的是 :

①在 Level 2 的輸出流,都是以功能來命名的。例如: Print , DataOutput , Buffered

②在 Level 3 的輸出流,則多數都是以資料源的形式來命名的。例如: ByteArray , File , Piped

是以說 Level 2 的輸出流必須依賴于 Level 3 的輸出流,實際上 Level 2 的輸出流,都繼承與一個叫做 FilterOutputStream 的輸出流

下面是對各個 output stream 的簡介:

① PrintStream

為底層的輸出流添加額外的功能,令到底層的輸出流可以友善地輸出各種經過“格式化”的資料。和其它輸出流不同,該輸出流并不會抛出 IOException ,但是可以通過c heckError 方法來檢查是否有異常發生。

該輸出流具備自動 flush 功能,但寫完一個位元組數組,或者碰到一個 println 方法的調用,或者當要寫出的字元是換行符時。會自動清空 flush 。

預設情況下所有要寫出的記憶體字元,都會被該輸出流以平台預設編碼方式,轉換為位元組流輸出

② DataOutputStream

允許應用程式直接将基本類型資料 (boolean, char, byte) 直接寫出到底層的輸出流 ( 内部轉換為适當的位元組 )

③ BufferedOutputStream

為底層的輸出流提供“緩沖”的功能,所有的寫出請求和要寫出的資料都會先緩沖到該輸出流的緩沖區中,在适當的時機一次性寫出。

注意該類的 write 方法被調用時并不一定立即将記憶體中的資料寫出到資料源,而可能先将資料緩存起來。

④ ByteArrayOutputStream

該輸出流能夠将要寫入記憶體的位元組,先緩存到自身的緩沖區中。并且該緩沖區的大小可以自動增長。如果要從該輸出流中提取位元組,可以使用 toByteArray ,如果要還原為字元串,可以使用 toString 。

關閉該輸出流并不會産生任何的 IOException ,因為它的輸出端是 --- 記憶體而非檔案。

⑤ FileOutputStream

該輸出流以原始位元組 (raw bytes) 的方式向底層檔案系統中寫資料。在某些系統下,有時候隻允許同一個檔案

打開一個輸出流。是以如果該檔案已經被打開了,則再次打開一個輸出流會抛出異常。

【三】基于字元的輸入流

java io流讀寫檔案換行_IO與檔案讀寫---Java的IO流架構

值得注意的地方有:

① Level 2 的輸入流,大多數都會指明資料源的形式:例如 CharArray , String , File

② Level 3 的輸入流,則不會在出現具體的資料源名字,而是以功能取代:例如 Buffered , LineNumber

但是和基于位元組的輸入流結構不同, FileInputStream 是直接繼承于 InputStream 類的。但是 FileReader 卻是繼承與 InputStreamReader 的。而且 BufferedReader 不是繼承于 FilterReader 。看看下面的結構:

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

這時為什麼呢?其實如果我們知道 InputStreamReader 的作用是什麼就知道了:它的作用是充當一座基于位元組流和字元流之間轉換的橋梁。它将從位元組流讀取的位元組按照編碼轉換成字元。

實際上任何對檔案的 IO 讀寫,最終都是以位元組的形式進行的。是以讀取 ” 字元 ” 隻不過是一種邏輯上的說法,那麼 FileReader 為什麼繼承于 InputStreamReader 就可以了解了。

下面是對各個 Reader 的介紹:

① CharArrayReader

直接從記憶體中以“字元”的形式讀取資料。每次讀取一個字元,存放到緩存區中。

② FileReader

從文本檔案中讀取字元的字元輸入流,該字元輸入流使用系統預設的字元集編碼和緩存區大小,不能更改。如果需要重新調整輸入流的編碼,必須使用 InputStreamReader 。

③ StringReader

從一個字元串中讀取内容

④ BufferedReader

為其它的基于字元的輸入流提供緩沖功能以提高效率。通常情況下,對于底層輸入流的任何一次 read 或者 readLine 請求都将導緻直接的磁盤通路,這将導緻效率非常地下。

當使用緩存的字元輸入流時,讀取請求将被緩存,在合适的時候一次性讀入批量資料,再進行編碼轉換。以此顯著提高效率。 這個緩存輸入流的緩沖區大小是可以指定的。

⑤ LineNumberReader

可以跟蹤讀入的“行資料”的字元輸入流。該輸入流内置一個訓示器,用于跟蹤讀入的資料的行數。預設情況下行号從 0 開始。使用者可以通過 setLineNumber 和 getLineNumber 來設定 / 或者行号。一個行可以由“換行符”,“回車符”,“回車換行符”辨別。當遇到其中任意一個符号時,訓示器的值将增加1。

注意的是: setLineNumber 方法并不會真正地改變資料在檔案中的實體位置,而是簡單地修改了訓示器的數值而已。

【四】基于字元的輸出流

java io流讀寫檔案換行_IO與檔案讀寫---Java的IO流架構

值得注意的是 :

①在 Level 2 的輸出流,都是以功能來命名的。例如: Print , Buffered

②在 Level 3 的輸出流,則多數都是以資料源的形式來命名的。例如: CharArray , File , String

是以說 Level 2 的輸出流必須依賴于 Level 3 的輸出流,實際上 Level 2 的輸出流,都繼承與一個叫做 FilterWriter 的輸出流

① PrintWriter

将對象資料以恰當的格式輸出到文本輸出流,和 PrintOutputStream 類不同,後者當碰到換行符的時候會清空緩沖區。但是 PrintWriter 不會,它隻在 print 方法被調用時才會清空緩存。是以理論上來說它要比 PrintOutputStream 更加高效,因為隻要緩沖區允許,它可以接納更多的内容而一次性寫入到檔案。

這個類使用系統預設的行分割符來代替“換行符 "n ”,因為不是所有的系統都是通過“ "n ”來換行的。

② BufferedWriter

為其它字元輸出流提供緩沖功能,該輸出流的緩沖區大小可以設定,否則将使用預設的緩沖區大小。這個類有一個 newLine 方法,用于傳回一個基于系統的行分割符,而非一定是“ "n ”。這個類會緩存寫請求,當要寫出的字元達到一定程度時就一次性地寫出到底層的檔案輸出流。

③ CharArrayWriter

類似于 ByteArrayOutputStream ,向記憶體中寫字元。其中内置一個緩沖區,大小可以動态增長。如果要得到寫入的字元可以使用 toCharArray 方法,如果要構造出字元串則可以使用 toString 方法。

④ FileWriter

以基于字元的方式向檔案中寫資料。該輸出流使用系統平台預設的字元集編碼方式和緩存區大小,不能設定改變。如果需要的話可以使用 OutputStreamWriter。

某些系統隻允許同一時刻一個檔案被一個輸出流打開,是以假如檔案已經被另外的輸出流打開了,那麼新的輸出流試圖打開同一個檔案時将抛出異常。

【五】位元組流和字元流之間的轉換 ①InputStreamReader: 将位元組流--》字元流,預設使用系統編碼,可另外指定編碼方式。是一個解碼過程

java io流讀寫檔案換行_IO與檔案讀寫---Java的IO流架構

new BufferedReader(new InputStreamReader(System.in))

②OutputStreamWriter: 将字元流--》位元組流,預設使用系統編碼,可另外指定編碼方式。是一個編碼過程

new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out));