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的大小默认是
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到底代表什么的更多相关文章
- MySQL中int(5) 中的5代表什么意思?
对于INT型,MySQL支持指定显示宽度例如:int(5):表示如果数值宽度小于5位,则填满宽度,保证总宽度为5位.默认为int(11),配合zerofill可以看到效果. DROP TABLE IF ...
- JavaWEB开发中的/到底代表什么
- msyql int(x) 中的x
先看一个mysql表结构 Sql代码 CREATE TABLE `test` ( `TYPEID` int (2) ) ENGINE=MyISAM CHARSET=latin1; Sql代码 ...
- 下面的程序段创建了BufferedReader类的对象in,以便读取本机c盘my文件夹下的文件1.txt。File构造函数中正确的路径和文件名的表示是( )。
下面的程序段创建了BufferedReader类的对象in,以便读取本机c盘my文件夹下的文件1.txt.File构造函数中正确的路径和文件名的表示是( ). ./表示当前项目的路径../表示当 ...
- BufferedReader类
BufferedReader类用于从缓冲区中读取内容,多有的输入字节数据都将放在缓冲区中. BufferedReader中定义的构造方法只能接收字符输入流的实例,所以必须使用字符输入流和字节输入流的转 ...
- Java :BufferedWriter类和BufferedReader类的构造方法、主要方法
BufferedWriter 和 BufferedReader 为带有默认缓冲的字符输出输入流,因为有缓冲区所以效率比没有缓冲区的高. 一.BufferedWriter 类 构造方法:buffered ...
- 字节流和字符流(BufferedReader类和BufferedWriter类)
一般情况下,为了提高字符文件读/写效率,通常需要为文件读/写器添加一个缓冲读/写器,分别为BufferedReader类和BufferedWriter类. 1:BufferedReader类 假如上面 ...
- java.util.Random 类的 nextInt(int num )
随机产生3个67~295的整数并找出数值居中的数 并输出中间的数例如:100,225和200,输出200 要随机产生某个范围内的整数,用 java.util.Random 类的 nextInt(int ...
- java中String是对象还是类?详解java中的String
有很多人搞不懂对象和类的定义.比如说java中String到底是对象还是类呢? 有人说String 既可以说是类,也可以说是对象. 其实他这么说也没问题, 类和对象其实都是一个抽象的概念. 我们可以把 ...
随机推荐
- Gitlab源码库里代码提交后,如何触发jenkins自动构建?
版本库里代码提交后,如何触发jenkins自动构建?这是一个面试题,感觉自己回答的并不好,因为并没有用过这个功能,之前公司实际项目用的是svn版本管理,一般都用立刻构建,和定时任务构建(不管代码是否有 ...
- Ruby入坑指南
1.1 简介 Ruby语言是由松本行弘(Matz)设计,是一门通用的.面向对象的.解释型语言. 1.2 Ruby?RUBY?ruby? 1.Ruby:用来表示编程的语言 2.ruby:是指一个计算机程 ...
- .net问号的作用
??运算符(C# 参考)http://msdn.microsoft.com/zh-cn/library/ms173224.aspx 可以为 null 的类型(C# 编程指南)http://msdn.m ...
- slice 与 splice 的区别
slice: 定义一个数组:let b = ['a','b','c','d','e'] b:["a", "b", "c", "d& ...
- 一脸懵逼学习Storm---(一个开源的分布式实时计算系统)
Storm的官方网址:http://storm.apache.org/index.html 1:什么是Storm? Storm是一个开源的分布式实时计算系统,可以简单.可靠的处理大量的数据流.被称作“ ...
- 随心测试_软测基础_001<说在开始_测试理念>
- php框架之phalcon
1.开发助手 1) 下载 git clone https://github.com/phalcon/cphalcon.git git clone https://github.com/phalcon/ ...
- vue.js 列表追加项写法
<ul id="app"> <template v-for="site in sites"> <li>{{ site.nam ...
- WebSocket介绍,与Socket的区别
WebSocket介绍与原理 WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex).一开始的握手需要借助HTTP请求完成. ——百 ...
- 使用ffmpeg将Mp4转gif
视频转动图,是个强需求,家大业大的微博相册只可上传图片,进而基于微博相册的生态也是如此.目前,网络上有许多转换.压缩的网站,多数执行速度慢或者收费,体验较差. ffmpeg是一个开源的音频处理软件,支 ...