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

关于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)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值