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 既可以说是类,也可以说是对象. 其实他这么说也没问题, 类和对象其实都是一个抽象的概念. 我们可以把 ...
随机推荐
- WPF 控件之 Popup
1.经常使用属性说明 IsOpen: 布尔值,指示 Popup 控件是否显示 StaysOpen: 布尔值,指示在 Popup 控件失去焦点的时候,是否关闭 Popup 控件的显示 PopupAnim ...
- resnet代码分析
1. 先导入使用的包,并声明可用的网络和预训练好的模型 import torch.nn as nn import torch.utils.model_zoo as model_zoo #声明可调用的网 ...
- Linux基本操作
1. ctr + alt + t 打开新的终端窗口2. ctr + shift + + 终端窗口字体放大3. ctr + - 终端窗口字体缩小4. ls : 查看目录下的文件信息5. pwd: 查看目 ...
- Codeforces Goodbye 2018
Goodbye 2018 可能是我太菜考试的时候出不了$E$ 可能是我太菜考试的时候调不出$F$ 所以转化为手速场之后手速还上不去.jpg A 模拟题意... #include <cstdio& ...
- jQuery的一些简单基础知识
### 什么是jQuery?jQuery(js+Query)是一款优秀的JavaScript库,帮助开发人员用最少的代码做更多的事情,官网网站http://jquery.com/ ### 为什么学习j ...
- JS 设计模式六 -- 代理模式
概念 为一个对象提供一个代用品或占位符,以便控制对它的访问. 当客户不方便直接访问一个对象的时候,需要提供一个替身对象来控制对这个对象的访问. 替身对象对请求做出一些处理之后, 再把请求转交给本体对象 ...
- Photoshop给人像加上个性裂纹肌肤
1.打开人物及纹理素材图片,把素材图片拖到人物图片里面,适当降低图层不透明度. 2.选择菜单:编辑 > 变形 > 自由变形,使纹理位置合适,然后确定. 3.用橡皮工具擦除多余的地方. 4. ...
- 技术的极限(6): 密码朋克精神(Cypherpunk Spirit)
上一篇:技术的极限(5): 识别计算与技术背后的心智 下一篇:技术的极限(7): 处理复杂与分层 目录: ** 0x01 数据和App分离 ** 0x02 蒸汽朋克/赛博朋克/密码朋克 ** 0x03 ...
- springboot实现简单的文件上传
承接上一篇,这里记录一下简单的springboot文件上传的方式 首先,springboot简单文件上传不需要添加额外的jar包和配置 这里贴一下后端controller层的实现代码 补一份前台的HT ...
- XPath、CSS 选择器 -学习地址
http://www.w3school.com.cn/cssref/css_selectors.asp http://www.w3school.com.cn/xpath/xpath_syntax.as ...