我应该始终将 InputStream 包装为 BufferedInputStream 吗?

问题描述 投票:0回答:4

当我知道给定的

InputStream
是否是
buffered
以外的东西时,始终将
BufferedInputStream
包装为 InputStream 是否有意义?

例如:

InputStream is = API.getFromSomewhere()
if (!(is instanceof BufferedInputStream)) {
    return new BufferedInputStream(is);
}

return is;
java stream java-io
4个回答
38
投票

当我知道给定的InputStream是否是缓冲以外的东西时,always将InputStream包装为BufferedInputStream是否有意义?

没有。

如果您可能执行大量小读取(一次一个字节或几个字节),或者如果您想使用缓冲 API 提供的一些更高级别的功能,那么这是有意义的;例如

BufferedReader.readLine()
方法。

但是,如果您只想使用

read(byte[])
和/或
read(byte[], int, int)
方法执行大块读取,则将
InputStream
包装在
BufferedInputStream
中并没有帮助。

(回应 @Peter Tillman 对他自己的答案的评论,块读取用例绝对代表超过

InputStream
类的使用的 0.1%!但是,他是正确的,因为它通常是 无害在不需要时使用缓冲 API。)


7
投票

我不会这样做,我会将其保留在尽可能的最高抽象级别。如果您不打算使用 BufferedStream 的标记和重置功能,为什么还要包装它呢?

如果消费者需要的话,最好把它包裹在那里。


3
投票

您可能并不总是需要缓冲,因此,答案是否定的,在某些情况下,这只是开销。

“不”还有另一个原因,而且可能更严重。当您在套接字上启用超时时,与网络套接字一起使用时,

BufferedInputStream
(或
BufferedReader
)可能会导致不可预测的故障。读取数据包时可能会发生超时。您将无法再访问传输到该点的数据 - 即使您知道存在一些非零字节数(请参阅
java.net.SocketTimeoutException
,它是
java.io.InterruptedIOException
的子类,因此具有
bytesTransferred
变量可用)。

如果您想知道在读取时如何发生套接字超时,只需考虑调用

read(bytes[])
方法,并且包含消息的原始数据包最终被拆分,但其中一个部分数据包被延迟超过超时(或剩余的数据包)超时的一部分)。当再次包装在实现
java.io.DataInput
的内容中时,这种情况可能会更频繁地发生(任何多字节值的读取,例如
readLong()
readFully()
BufferedReader.readLine()
方法。

请注意,

java.io.DataInputStream
对于具有超时的套接字流来说也是一个不好的候选者,因为它在超时异常方面也表现不佳。


1
投票

这还取决于您将如何从 InputStream 中读取数据。 如果您打算一次读取一个字符/字节(即 read()),那么 BufferedInputStream 将通过代表您安静地进行批量读取来减少您的开销。 如果您打算一次将其读入 4k 或 8k 字节/字符数组,那么 BufferdInputStream 可能不会给您带来好处。

© www.soinside.com 2019 - 2024. All rights reserved.