使用 BufferedInputStream 包装后对原始 InputStream 的影响
Posted
技术标签:
【中文标题】使用 BufferedInputStream 包装后对原始 InputStream 的影响【英文标题】:Effect on the original InputStream after wrapping with BufferedInputStream 【发布时间】:2014-02-12 07:52:16 【问题描述】:假设我有一个接收 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()
编辑: 我想我所要求的内容很笼统,因此需要做很多工作。至于我正在做的事情,我实际上不需要完整的标记和重置功能,所以我找到了一个小工作。但是,我将把问题的第二部分留在这里,所以请随意尝试这个问题:)。
【问题讨论】:
【参考方案1】:http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#BufferedInputStream%28java.io.InputStream%29
看起来 BufferedInputStream 使用 InputStream 来执行对数据流的操作。 Buffered 类只是实现了一个内部使用的缓冲区数组。
不知道你可以用什么代替,除了可能复制 InputStream 以便你有第二个对象可以调用。
【讨论】:
【参考方案2】:BufferedInputStream
的默认 bufferSize 为 8192,因此当您从 BufferedInputStream
读取数据时,它会尝试填充其缓冲区。因此,如果您必须从InputStream
读取的字节数少于bufferSize
,那么您的InputStream
的全部内容将被读取到缓冲区,因此在从BufferedInputStream
看看BufferedInputStream
源代码:http://www.docjar.com/html/api/java/io/BufferedInputStream.java.html
【讨论】:
【参考方案3】:BufferedInputStream
将分批预加载底层InputStream
的数据,这将触发底层InputStream
仓位的相应移动。如果缓冲区大小足以一次性消耗底层流中的所有数据,您可能会很好地观察到您描述的行为。
【讨论】:
【参考方案4】:两件事:
任何接受流作为输入参数的 API 都可能会使用该流,因此调用者期望流保持任何可用状态是不合理的。也许 java 流类以某种方式强制执行单一所有权以使这一点更清楚会更好。
作为一种特殊情况,BufferedInputStream 将使用它“包装”的底层流,因为正如其他人所指出的那样,它通过缓冲块读取来实现(一种有限形式的)标记和重置。
【讨论】:
【参考方案5】: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()来查看小文件和大文件的区别。
【讨论】:
以上是关于使用 BufferedInputStream 包装后对原始 InputStream 的影响的主要内容,如果未能解决你的问题,请参考以下文章
缓冲输入输出流[也叫包装流] BufferedInputStream,BufferedOutputStream,BufferedReader和BufferedWriter
J05-Java IO流总结五 《 BufferedInputStream和BufferedOutputStream 》