假设我有一个接受InputStream的方法。
此方法需要使用BufferedInputStream包装此InputStream以使用其标记和重置功能。但是,传入的InputStream可能仍然由方法的调用者使用。
public static void foo(InputStream is) throws Exception {
BufferedInputStream bis = new BufferedInputStream(is);
int b = bis.read();
}
public static void main(String[] args) {
try {
InputStream is = new FileInputStream(someFile);
foo(is);
int b = is.read(); // return -1
}catch (Exception e) {
e.printStackTrace();
}
}
我的问题是:当读取(或初始化)BufferedInputStream时,原始InputStream究竟发生了什么?
我的假设是,如果读取BufferedInputStream,原始InputStream也将向前移动。但是,在调试我的代码之后,我发现InputStream在读取时将返回-1。
如果在这样的过程之后原始的InputStream不可读,我应该如何实现我的目的:
InputStream is;
foo(is); // Method only take in generic InputStream object
// Processing of the passed in InputStream object require mark and reset functionality
int b = is.read(); // Return the next byte after the last byte that is read by foo()
编辑: 我想我要求的是非常通用的,因此需要做很多工作。至于我正在做什么,我实际上并不需要满分和标记。重置功能所以我找到了一个小工作。但是,我会在这里留下问题的第二部分,所以请随意尝试这个问题:)。
答案 0 :(得分:1)
BufferedInputStream
的默认bufferSize是8192,所以当你从BufferedInputStream
读取时,它会尝试填充它的缓冲区。因此,如果您必须读取InputStream
字节而不是bufferSize
,那么InputStream
的完整内容将被读取到缓冲区,因此您获得-1后阅读BufferedInputStream
查看BufferedInputStream
源代码:http://www.docjar.com/html/api/java/io/BufferedInputStream.java.html
答案 1 :(得分:0)
看起来BufferedInputStream使用InputStream来执行使用数据流执行的操作。 Buffered类只是实现了一个供内部使用的缓冲区数组。
不确定你可以使用什么,除了复制InputStream以便你有第二个要调用的对象。
答案 2 :(得分:0)
BufferedInputStream
将批量预加载基础InputStream
的数据,这将触发基础InputStream
位置的相应移动。如果缓冲区大小足以一次性消耗基础流中的所有数据,您可能会观察到您描述的行为。
答案 3 :(得分:0)
两件事:
任何接受流作为输入参数的API都可能会使用该流,因此调用者期望流保持任何类型的可用状态是不合理的。也许最好让java流类以某种方式强制执行单一所有权以使其更清晰。
作为一种特殊情况,BufferedInputStream将使用它“包装”的底层流,因为它实现了(有限形式的)标记并通过缓冲块读取来重置,正如其他人所指出的那样。
答案 4 :(得分:0)
private static class MybufferedInputStream extends BufferedInputStream {
public MybufferedInputStream(InputStream in) {
super(in);
}
public int getBufferSize(){
int i=0;
for (Byte byte1 : super.buf) {
if (byte1!=0) {
i++;
}
}
return i;
}
}
然后你可以在read()之后调用getBufferSize()来查看小文件和更大文件之间的区别。