您的位置:首页 > Web前端

关于BufferedInputStream类的mark与reset方法的一个bug的问题

2010-11-26 18:51 537 查看
关于BufferedInputStream类的mark与reset方法的一个bug的问题.txt

sylilzy@gmail.com
施祖阳 http://www.shizuyang.cn

2010-7-7 13:20:26 星期三

最近在调试程序时发现BufferedInputStream类的mark与reset方法存在一个bug,重现方式如下:

import java.io.BufferedInputStream;

import java.io.FileInputStream;

public class BugTest {

/**

* @param args

*/

static public void main(String[] p) throws Exception {

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("e://temp//a.txt"));

int available = bis.available();

System.out.println("available:" + available);

// ---

int markLimit = available;

bis.mark(markLimit);

System.out.println("---mark:" + markLimit);

byte[] temp = new byte[available];

bis.read(temp);

System.out.println("---read:" + available);

System.out.println("---read one byte:" + bis.read());

bis.reset();

System.out.println("reset ok!");

bis.close();

}

}

在以上类运行时,如果e://temp//a.txt文件的大小在8192字节以上,则运行结果如下:

available:8384

---mark:8384

---read:8384

---read one byte:-1

Exception in thread "main" java.io.IOException: Resetting to invalid mark

at java.io.BufferedInputStream.reset(Unknown Source)

at com.BugTest.main(BugTest.java:22)

如果e://temp//a.txt文件的大小在8192字节以下,则不会有此异常。

为了分析问题产生的原因,我写了如下一个类来显示BufferedInputStream类的相关信息:

import java.io.BufferedInputStream;

import java.io.InputStream;

public class MyBuffer extends BufferedInputStream {

public MyBuffer(InputStream in, int size) {

super(in, size);

// TODO Auto-generated constructor stub

}

public MyBuffer(InputStream in) {

super(in);

// TODO Auto-generated constructor stub

}

public int getMarklimit() {

return marklimit;

}

public int getMarkPosition() {

return markpos;

}

public int getBufferLength() {

return buf.length;

}

}

测试类修改如下:

import java.io.*;

import java.util.regex.Pattern;

/**

* @author shizy TODO To change the template for this generated type comment go

* to Window - Preferences - Java - Code Style - Code Templates

*/

public class Test {

static public void main(String[] p) throws Exception {

MyBuffer bis = new MyBuffer(new FileInputStream("e://temp//a.txt"));

int available = bis.available();

System.out.println("available:" + available);

System.out.println("getBufferLength:" + bis.getBufferLength());

System.out.println("getMarklimit:" + bis.getMarklimit());

System.out.println("getMarkPosition:" + bis.getMarkPosition());

// ---

int markLimit = available;

bis.mark(markLimit);

System.out.println("---mark:" + markLimit);

System.out.println("getBufferLength:" + bis.getBufferLength());

System.out.println("getMarklimit:" + bis.getMarklimit());

System.out.println("getMarkPosition:" + bis.getMarkPosition());

byte[] temp = new byte[available];

bis.read(temp);

System.out.println("---read:" + available);

System.out.println("getBufferLength:" + bis.getBufferLength());

System.out.println("getMarklimit:" + bis.getMarklimit());

System.out.println("getMarkPosition:" + bis.getMarkPosition());

System.out.println("---read one byte:" + bis.read());

System.out.println("getBufferLength:" + bis.getBufferLength());

System.out.println("getMarklimit:" + bis.getMarklimit());

System.out.println("getMarkPosition:" + bis.getMarkPosition());

bis.reset();

System.out.println("reset ok!");

bis.close();

}

}

则运行结果如下:

available:8384

getBufferLength:8192

getMarklimit:0

getMarkPosition:-1

---mark:8384

getBufferLength:8192

getMarklimit:8384

getMarkPosition:0

---read:8384

getBufferLength:8384

getMarklimit:8384

getMarkPosition:0

---read one byte:-1

getBufferLength:8384

getMarklimit:8384

getMarkPosition:-1

Exception in thread "main" java.io.IOException: Resetting to invalid mark

at java.io.BufferedInputStream.reset(Unknown Source)

at com.Test.main(Test.java:41)

可见,在输出了“---read:8384”后,BufferLength变成了与Marklimit一样的大小,但在"---read one byte:-1"后,MarkPosition变成了-1,导致了reset时出错。

解决办法有三种:

1.增加BufferedInputStream的BufferLength,在上例中,增加到8385则可解决问题。但此大小需要由输入流的数据量解定,此方法并不太可行。

2.改变markLimit大小。将int markLimit = available;修改为:int markLimit = available+1;。采用这种方式,则上例运行结果如下:

available:8384

getBufferLength:8192

getMarklimit:0

getMarkPosition:-1

---mark:8385

getBufferLength:8192

getMarklimit:8385

getMarkPosition:0

---read:8384

getBufferLength:8385

getMarklimit:8385

getMarkPosition:0

---read one byte:-1

getBufferLength:8385

getMarklimit:8385

getMarkPosition:0

reset ok!

3.不要在流数据结束之后再调用bis.read方法,这种方法并不能完全保证不出问题,因为流数据是否结束,必须要通过read的返回值才能知道。

看来,此问题的出现情况是当BufferLength刚好与从输入流读入的数据相等时(缓冲区会随着marklimit大小增长),如果再读入数据,即时此时未读入数据,则也会认为超过了Marklimit限制,则reset会抛出异常。

注:

jdk版本:

java version "1.6.0_05"

Java(TM) SE Runtime Environment (build 1.6.0_05-b13)

Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: