昨天用到了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的大小默认是

 private static int defaultCharBufferSize = 8192;

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

public BufferedReader(Reader in, int sz)

来指定。

关键的部分是fill方法的代码

 private void fill() throws IOException {
int dst;
if (markedChar <= UNMARKED) {
/* No mark */
dst = 0;
} else {
/* Marked */
int delta = nextChar - markedChar;
if (delta >= readAheadLimit) {
/* Gone past read-ahead limit: Invalidate mark */
markedChar = INVALIDATED;
readAheadLimit = 0;
dst = 0;
} else {
if (readAheadLimit <= cb.length) {
/* Shuffle in the current buffer */
System.arraycopy(cb, markedChar, cb, 0, delta);
markedChar = 0;
dst = delta;
} else {
/* Reallocate buffer to accommodate read-ahead limit */
char ncb[] = new char[readAheadLimit];
System.arraycopy(cb, markedChar, ncb, 0, delta);
cb = ncb;
markedChar = 0;
dst = delta;
}
nextChar = nChars = delta;
}
} int n;
do {
n = in.read(cb, dst, cb.length - dst);
} while (n == 0);
if (n > 0) {
nChars = dst + n;
nextChar = dst;
}
}

第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 的缓存。

可以写程序来验证结论来验证一下

 class a {
public static void main(String args[])// throws Exception
{
FileInputStream fis = null;
try {
fis = new FileInputStream("新建文本文档.txt");
InputStreamReader instream = new InputStreamReader(fis, "gbk"); BufferedReader br = new BufferedReader(instream, 20);//buffersize=20 for (int i=0; i<10; i++) {
br.read();
} br.mark(10);//markedChar=10, readAheadLimit = 10 20-10=10 buffersize-markedChar>=readAheadLimit ,所以抛出异常 for (int i=0; i<15; i++) {
br.read();
}
br.reset();
} catch(Exception e) {
System.out.println("在catch里面"+e);
} finally {
}
}
}//运行结果:在catch里面java.io.IOException: Mark invalid
 import java.io.*;
import java.lang.Exception; class a {
public static void main(String args[])// throws Exception
{
FileInputStream fis = null;
try {
fis = new FileInputStream("新建文本文档.txt");
InputStreamReader instream = new InputStreamReader(fis, "gbk"); BufferedReader br = new BufferedReader(instream, 20);//buffersize=20 for (int i=0; i<10; i++) {
br.read();
} br.mark(11);//markedChar=10, readAheadLimit = 11    20-10=10 < 11 buffersize-markedChar<readAheadLimit ,所以不抛出异常 for (int i=0; i<15; i++) {
br.read();
}
br.reset();
} catch(Exception e) {
System.out.println("在catch里面"+e);
} finally {
}
}
}//程序运行后什么也不输出

BufferedReader类里面mark(int readAheadLimit)中readAheadLimit到底代表什么的更多相关文章

  1. MySQL中int(5) 中的5代表什么意思?

    对于INT型,MySQL支持指定显示宽度例如:int(5):表示如果数值宽度小于5位,则填满宽度,保证总宽度为5位.默认为int(11),配合zerofill可以看到效果. DROP TABLE IF ...

  2. JavaWEB开发中的/到底代表什么

  3. msyql int(x) 中的x

    先看一个mysql表结构 Sql代码 CREATE   TABLE  `test` ( `TYPEID` int (2) ) ENGINE=MyISAM CHARSET=latin1; Sql代码   ...

  4. 下面的程序段创建了BufferedReader类的对象in,以便读取本机c盘my文件夹下的文件1.txt。File构造函数中正确的路径和文件名的表示是( )。

    下面的程序段创建了BufferedReader类的对象in,以便读取本机c盘my文件夹下的文件1.txt.File构造函数中正确的路径和文件名的表示是(    ). ./表示当前项目的路径../表示当 ...

  5. BufferedReader类

    BufferedReader类用于从缓冲区中读取内容,多有的输入字节数据都将放在缓冲区中. BufferedReader中定义的构造方法只能接收字符输入流的实例,所以必须使用字符输入流和字节输入流的转 ...

  6. Java :BufferedWriter类和BufferedReader类的构造方法、主要方法

    BufferedWriter 和 BufferedReader 为带有默认缓冲的字符输出输入流,因为有缓冲区所以效率比没有缓冲区的高. 一.BufferedWriter 类 构造方法:buffered ...

  7. 字节流和字符流(BufferedReader类和BufferedWriter类)

    一般情况下,为了提高字符文件读/写效率,通常需要为文件读/写器添加一个缓冲读/写器,分别为BufferedReader类和BufferedWriter类. 1:BufferedReader类 假如上面 ...

  8. java.util.Random 类的 nextInt(int num )

    随机产生3个67~295的整数并找出数值居中的数 并输出中间的数例如:100,225和200,输出200 要随机产生某个范围内的整数,用 java.util.Random 类的 nextInt(int ...

  9. java中String是对象还是类?详解java中的String

    有很多人搞不懂对象和类的定义.比如说java中String到底是对象还是类呢? 有人说String 既可以说是类,也可以说是对象. 其实他这么说也没问题, 类和对象其实都是一个抽象的概念. 我们可以把 ...

随机推荐

  1. 解释型语言VS编译型语言

    前言 计算机不能直接理解除机器语言以外的语言,所以只有把程序员编写的程序翻译成机器语言,计算机才能够执行程序. 将其他语言翻译成机器语言的工具,被称之为:编译器. 编译器的翻译方式有两种:编译和解释. ...

  2. 正则表达式,提取html标签的属性值

    /** * 提取HTML标签的属性值 * @param source HTML标签内容 * "<a title=中国体育报 href=''>aaa</a><a ...

  3. 前端部署ant+yuicompressor文件压缩+获取版本+SSH公布(部分代码)

    文件压缩: <apply executable="java" parallel="false" failonerror="true" ...

  4. oracle 基础查询语句

    select abs(10) from dual; --取绝对值select ceil(3.6) from dual;--向上取整 select power(2,3) from dual;--2的3次 ...

  5. 好程序员技术分享html5和JavaScript的区别

    好程序员技术分享html5和JavaScript的区别,HTML5广义上讲是前端开发学科的代名词,包含HTML5.CSS3及JavaScript三个重要的部分,是运行在浏览器上应用的统称.如PC端网站 ...

  6. vue移动端常用组件

    3d picker组件 参考链接:https://segmentfault.com/a/1190000007253581?utm_source=tag-newest安装:npm install vue ...

  7. phpcms不能批量更新栏目页和内容页

    需要给网站根目录更加users用户的写入权限.

  8. java基础-01基本概念

    java的特点 跨平台 所谓的平台,我们可以理解为操作系统. 大部分语言是不能跨平台的,比如c语言的程序在windows和linux上需要编写不同的代码. java程序是运行在JVM(Java Vir ...

  9. 【问题解决方案】ImportError: No module named 'pygal'

    <Python编程:从入门到实践>一书,第二个项目-可视化,第四节用到pygal 安装部分用 'python -m pip install pygal==1.7' 安装,但使用时仍然报错 ...

  10. Centos6.5 pppoe-server

    [root@localhost network-scripts]# rpm -q rp-pppoepackage rp-pppoe is not installed ----------------- ...