在java中缓冲缓冲流的结果是什么?

时间:2013-09-28 13:01:17

标签: java stream java-io bufferedinputstream

正在编写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);

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

3 个答案:

答案 0 :(得分: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)会产生影响。)

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分: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)。如果您使用双缓冲区将数据假脱机到内存中,然后将该数据刷回内存。这在速度方面确实有成本......