3

正在为以下内容编写 javadoc:

/**
 * ...Buffers the input stream so do not pass in a BufferedInputStream ...
 */
public static void meth(InputStream is) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(is,
            INPUT_STREAM_BUFFER_SIZE);
    // rest omitted
}

但是传入缓冲的输入流真的有问题吗?所以这 :

InputStream is = new BufferedInputStream(new FileInputStream("C:/file"), SIZE);
meth(is);

会缓冲isbis- 还是 java 会检测到is已经缓冲并设置bis = is?如果是,不同的缓冲区大小会有所不同吗?如果没有,为什么不呢?
注意:我说的是输入流,但实际上这个问题对输出流也有效

4

3 回答 3

4

但是传入缓冲的输入流真的有问题吗?

并不真地。这样做可能会产生很小的开销,但与读取输入的总成本相比,它可以忽略不计。

如果您查看 , 的代码BufferedInputStream(例如read1方法),您会发现当缓冲流被堆叠时,块读取被实现为高效。

[重新示例代码:] java 会检测到已经缓冲并设置了bis = is吗?

不。

如果没有,为什么不呢?

因为 Java(语言,编译器)通常不理解 Java 库类的语义。在这种情况下,由于这种优化的好处可以忽略不计,因此不值得实施。

当然,你可以自由地写你的meth方法来明确地做这种事情......虽然我预测它不会有什么不同。


我不太明白为什么在 read1 中,只有在请求的长度小于 buf.length (或者输入流中有标记的位置)时,它们才会“打扰”复制到输入缓冲区

我假设您指的是这段代码(在 中read1):

    if (len >= getBufIfOpen().length && markpos < 0) {
        return getInIfOpen().read(b, off, len);
    }

第一部分是说,如果用户要求的缓冲区大小小于流的配置缓冲区大小,我们不想使缓冲短路。(否则,我们会遇到一个问题,即read(byte[], int, int)使用较小的请求长度执行 a 会很糟糕。)

第二部分与标记/重置的实现方式有关。BufferedInputStreama使用缓冲区来实现它,而不是在底层流(可能支持也可能不支持)上使用标记/重置。你所看到的就是这个逻辑的一部分。(您可以自己处理细节......阅读源代码中的注释。)

于 2013-09-28T13:29:25.867 回答
1

如果您将流缓冲两次,那么它将使用更多的内存并且比只缓冲一次的速度要慢,但它仍然可以工作。

当然值得记录您的流确实缓冲,以便用户知道他们不需要自己这样做。

一般来说,最好是阻止而不是积极防止这种滥用。

于 2013-09-28T13:20:09.013 回答
0

答案是否定的,Java 不会检测到双缓冲。

避免此问题由用户决定。BufferedInputStream无法知道InputStream您传递给构造函数的参数是否被缓冲。

这是BufferedInputStream构造函数的源代码:

public BufferedInputStream(InputStream in, int size) {
    super(in);
    if (size <= 0) {
        throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
}

编辑

从评论来看,双缓冲流是否有问题?

简短的回答是肯定的。

缓冲的想法是提高速度,以便将数据假脱机到内存中并以块的形式写出(通常是非常慢的 IO)。如果双缓冲,则将数据假脱机到内存中,然后将该数据刷新到其他地方的内存中。就速度而言,这肯定是有代价的……

于 2013-09-28T13:07:53.043 回答