1. 程式人生 > >Java之IO(十一)BufferedReader和BufferedWriter

Java之IO(十一)BufferedReader和BufferedWriter

可能 pla lines 不能 循環 介紹 出現 簡單 描述符

  轉載請註明源出處:http://www.cnblogs.com/lighten/p/7074488.html

1.前言

  按照字節流的順序一樣,字符流也提供了緩沖字符流,與字節流不同,Java雖然提供了FilterReader和FilterWriter類,但是緩沖字符流沒有繼承者兩個類,而是直接繼承了Reader和Writer類。

2.BufferedReader

技術分享

  構造函數接受一個Reader和一個緩沖字符數量,默認8192。

技術分享

  read方法不但使用了同步鎖,還采取了for(;;)形式。nextChar是要讀取的字符位置下標,nChars是當前緩存中字符數量。很顯然,要讀取的字符下標大於等於當前存在的字符,意味著緩存中的字符已經被讀取完了,需要重新獲取寫入緩存。這個就是fill()方法。fill()之後還是沒有,就意味著讀取完了,返回-1。skipLF是否跳過換號符,默認false。然後就是返回位置為nextChar的cb字符數組的字符,自增1。

技術分享

  fill()方法需要考慮到mark方法產生的標記,有標記和無標記的情況是不同的,無標記的時候肯定就是buffer被使用完了,從0開始重新填數據。也就是最後一段了。有標記的時候就不能舍棄標記的數據了,所有需要計算dst的值,由於存在readAheanLimit參數所以mark的計算又有區別。這個參數的意思是重置標記的時候,之前讀取過的數據最多出現多少。因此,fill方法計算了標記位到已讀取完的長度,如果大於這個限制,這就是一個無效的標記(標記在1號位,讀完到5號位,但只能出現兩個歷史字符readAheanLimit,這樣標記位就沒有用了,因為不能刪除後面多余的字符吧,所以是一個無效標記)。有效標記又分為兩種情況,一種是readAheanLimit小於當前緩存大小,這個就不要緊,拷貝從標記為開始的數據就可以了。標記為置為0,新數據要從delta開始寫了。如果大於緩存,肯定就是重新創建緩存了。

技術分享

  read字符數組的方法也是一個常見的處理過程了,先執行一次,如果都完了就直接返回了,如果沒讀完,且沒有讀到需要的數量就通過while循環不斷讀,讀完了流就直接break,或者讀到所需的len長度。

技術分享

  如果沒有可讀的緩存了當然要重新fill,但是這裏也有一種情況,就是所要的長度超過緩存大小,這個時候就直接從原來的流中讀取返回。重填了之後還是沒有,就是讀取完了,返回-1。後面就是把數據填充到給的字符數組了,可能緩沖區的數據不夠,所以是選擇了小的那個值,然後返回。

  其它的方法沒上面好講的了。最後的一個lines方法,是JDK8才提供的,具體實現超過IO的範疇,作用是返回一個Stream<String>,裏面就是所讀取的流的一行行,懶加載的方式。

3.BufferedWriter

  相比於BufferedReader,輸出流BufferWriter較簡單些。

技術分享

  一樣接收一個Writer和緩存大小,默認也是8192個字符。

技術分享

  write方法,如果緩存寫滿了就刷入持有的writer。然後重置nextChar為0,寫入當前的這個位置。

技術分享

  裏面自己寫了一個比較方法,而沒有使用Math類的方法,理由上面也給了,使用完了文件描述符的時候,會嘗試打印堆棧跟蹤。

  其它兩個write方法都比較簡單,思路一樣,就不再繼續介紹了。

Java之IO(十一)BufferedReader和BufferedWriter