BufferedReader類裏面mark(int readAheadLimit)中readAheadLimit到底表明什麼

昨天用到了BufferedReader類裏面mark(int readAheadLimit)方法,對於文檔裏面readAheadLimit的解釋有些沒弄懂,就翻開源碼研究。具體的源碼分析能夠參見http://www.cnblogs.com/skywang12345/p/io_23.html ,這裏直接給出結論。html

當readAheadLimit的值小於等於BufferedReader裏面緩存的大小buffersize時,若是mark(readAheadLimit)後再讀取buffersize+1個字符,再reset()就會拋出異常,由於mark標記已經失效。java

當readAheadLimit的值大於BufferedReader裏面緩存的大小buffersize時,若是mark(readAheadLimit)後再讀取readAheadLimit+1個字符,再reset()就會拋出異常,由於mark標記已經失效。緩存

size = Math.max(readAheadLimit,buffersize),若是mark(readAheadLimit)後再讀取size+1個字符,再reset()就會拋出異常,由於mark標記已經失效。函數

-----------------刪除線部分不正確,下面的紅字纔是正確結論--------------------------------------源碼分析

爲何會讓mark失效?由於內存是有限的,當讀取了不少字符後一直要存着標記就會迫使緩存最少保存從mark位置的那個字符到mark+readAheadLimit個字符之間的字符。因此抄了這個readAheadLimit,會失效。spa

buffersize的大小默認是code

1 private static int defaultCharBufferSize = 8192;

這個默認值能夠經過構造函數htm

public BufferedReader(Reader in, int sz)

來指定。blog

關鍵的部分是fill方法的代碼內存

 1 private void fill() throws IOException {
 2         int dst;
 3         if (markedChar <= UNMARKED) {
 4             /* No mark */
 5             dst = 0;
 6         } else {
 7             /* Marked */
 8             int delta = nextChar - markedChar;
 9             if (delta >= readAheadLimit) {
10                 /* Gone past read-ahead limit: Invalidate mark */
11                 markedChar = INVALIDATED;
12                 readAheadLimit = 0;
13                 dst = 0;
14             } else {
15                 if (readAheadLimit <= cb.length) {
16                     /* Shuffle in the current buffer */
17                     System.arraycopy(cb, markedChar, cb, 0, delta);
18                     markedChar = 0;
19                     dst = delta;
20                 } else {
21                     /* Reallocate buffer to accommodate read-ahead limit */
22                     char ncb[] = new char[readAheadLimit];
23                     System.arraycopy(cb, markedChar, ncb, 0, delta);
24                     cb = ncb;
25                     markedChar = 0;
26                     dst = delta;
27                 }
28                 nextChar = nChars = delta;
29             }
30         }
31 
32         int n;
33         do {
34             n = in.read(cb, dst, cb.length - dst);
35         } while (n == 0);
36         if (n > 0) {
37             nChars = dst + n;
38             nextChar = dst;
39         }
40     }

第7行到第28行爲關鍵部分,調用fill方法的時機是第一次讀取時和緩存讀取完後接着讀取時,到底mark後讀取超過readAheadLimit個字符是否會清除readAheadLimit,取決於buffersize-markedChar與readAheadLimit的大小關係,若是buffersize-markedChar>=readAheadLimit,那麼超過readAheadLimit後reset會拋出異常,若是buffersize-markedChar<readAheadLimit那麼超過readAheadLimit不會拋出異常,能夠正常調用reset方法。這時候readAheadLimit的含義也就能夠理解了即mark後再讀取超過readAheadLimit說不是能正常的reset成功。buffersize的值在readAheadLimit > cb.length,即buffersize<readAheadLimit時讀取完buffer會致使分配一個大小爲readAheadLimit 的緩存。

能夠寫程序來驗證結論來驗證一下

 1 class a {
 2     public static void main(String args[])// throws Exception
 3     { 
 4         FileInputStream fis = null;
 5         try {
 6             fis = new FileInputStream("新建文本文檔.txt");
 7             InputStreamReader instream = new InputStreamReader(fis, "gbk");
 8         
 9             BufferedReader br = new BufferedReader(instream, 20);//buffersize=20
10 
11             for (int i=0; i<10; i++) {
12                 br.read();
13             }
14             
15             br.mark(10);//markedChar=10, readAheadLimit = 10    20-10=10 buffersize-markedChar>=readAheadLimit ,因此拋出異常
16 
17             for (int i=0; i<15; i++) {
18                 br.read();
19             }
20             br.reset();
21         } catch(Exception e) {
22             System.out.println("在catch裏面"+e);
23         } finally {
24         }
25     }
26 }//運行結果:在catch裏面java.io.IOException: Mark invalid
 1 import java.io.*;
 2 import java.lang.Exception;
 3 
 4 class a {
 5     public static void main(String args[])// throws Exception
 6     { 
 7         FileInputStream fis = null;
 8         try {
 9             fis = new FileInputStream("新建文本文檔.txt");
10             InputStreamReader instream = new InputStreamReader(fis, "gbk");
11         
12             BufferedReader br = new BufferedReader(instream, 20);//buffersize=20
13 
14             for (int i=0; i<10; i++) {
15                 br.read();
16             }
17             
18             br.mark(11);//markedChar=10, readAheadLimit = 11    20-10=10 < 11 buffersize-markedChar<readAheadLimit ,因此不拋出異常
19 
20             for (int i=0; i<15; i++) {
21                 br.read();
22             }
23             br.reset();
24         } catch(Exception e) {
25             System.out.println("在catch裏面"+e);
26         } finally {
27         }
28     }
29 }//程序運行後什麼也不輸出
相關文章
相關標籤/搜索