正在编写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
?如果是,不同的缓冲区大小会有所不同吗?如果不是,为什么不呢?
注意:我说的是输入流,但实际上问题对于输出流也是有效的
答案 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)。如果您使用双缓冲区将数据假脱机到内存中,然后将该数据刷回内存。这在速度方面确实有成本......