• 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 }//程序运行后什么也不输出
  • 相关阅读:
    php中json_encode中文编码问题
    PLSQL Developer建表时注释(COMMENT)中文乱码的解决方案(Windows)
    JQuery实现 checkbox 全选、反选,子checkbox有没选去掉全选
    oracle group by 使用
    oracle distinct 去除重复,同时按某字段排序
    phpstorm 设置多项目并存
    putty修改编码
    Java基本开发环境搭建
    smarty 判断变量是否为空
    vim
  • 原文地址:https://www.cnblogs.com/xxNote/p/6664592.html
Copyright © 2020-2023  润新知