【问题标题】:Effect on the original InputStream after wrapping with BufferedInputStream使用 BufferedInputStream 包装后对原始 InputStream 的影响
【发布时间】: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()

编辑: 我想我所要求的内容很笼统,因此需要做很多工作。至于我正在做的事情,我实际上不需要完整的标记和重置功能,所以我找到了一个小工作。但是,我将把问题的第二部分留在这里,所以请随意尝试这个问题:)。

【问题讨论】:

    标签: java inputstream bufferedinputstream


    【解决方案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】:

          两件事:

          1. 任何接受流作为输入参数的 API 都可能会使用该流,因此调用者期望流保持任何可用状态是不合理的。也许 java 流类以某种方式强制执行单一所有权以使这一点更清楚会更好。

          2. 作为一种特殊情况,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()来查看小文件和大文件的区别。

            【讨论】:

              猜你喜欢
              • 2011-02-27
              • 1970-01-01
              • 1970-01-01
              • 2011-06-24
              • 2013-03-29
              • 1970-01-01
              • 2011-05-18
              • 2016-11-30
              相关资源
              最近更新 更多