BufferedReader类里面mark(int readAheadLimit)中readAheadLimit到底代表什么

昨天用到了BufferedReader类里面mark(int readAheadLimit)方法,对于文档里面readAheadLimit的解释有些没弄懂,就翻开源码研究。具体的源码分析可以参见http://www.cnblogs.com/skywang12345/p/io_23.html ,这里直接给出结论。

当readAheadLimit的值小于等于BufferedReader里面缓存的大小buffersize时,如果mark(readAheadLimit)后再读取buffersize+1个字符,再reset()就会抛出异常,因为mark标记已经失效。

当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,会失效。

buffersize的大小默认是

1 private static int defaultCharBufferSize = 8192;

这个默认值可以通过构造函数

public BufferedReader(Reader in, int sz)

来指定。

关键的部分是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 }//程序运行后什么也不输出

 

转载于:https://www.cnblogs.com/xxNote/p/6664592.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值