Java 我是否应该始终将InputStream包装为BufferedInputStream?

Java 我是否应该始终将InputStream包装为BufferedInputStream?,java,stream,java-io,Java,Stream,Java Io,当我知道给定的InputStream是否不是缓冲的时,总是将InputStream包装为BufferedInputStream有意义吗?例如: InputStream is = API.getFromSomewhere() if(!(is instanceof BufferedInputStream)) return new BufferedInputStream(is); return is; 我不会那样做,我会把它放在尽可能高的抽象级别上。如果您不打算使用BufferedStream的

当我知道给定的InputStream是否不是缓冲的时,总是将InputStream包装为BufferedInputStream有意义吗?例如:

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

我不会那样做,我会把它放在尽可能高的抽象级别上。如果您不打算使用BufferedStream的标记和重置功能,为什么还要费心包装它呢


如果消费者需要它,最好将其包装在那里。

这还取决于您将如何从输入流中读取。如果要一次读取一个字符/字节(即read()),则BufferedInputStream将通过代表您进行批量读取来减少开销。如果要将它一次读取一个块到4k或8k字节/字符数组中,那么BuffredInputStream可能对您没有好处

当我知道给定的InputStream是否不是缓冲的时,总是将InputStream包装为BufferedInputStream有意义吗

没有

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

但是,如果您只打算使用
read(byte[])
和/或
read(byte[],int,int)
方法执行大数据块读取,则将
InputStream
包装在
BufferedInputStream
中没有帮助


(回应@Peter Tillman对他自己答案的评论,块读用例肯定代表了
InputStream
类的0.1%以上的使用!!然而,他是正确的,因为在不需要时使用缓冲API通常是无害的。)

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

“不”还有另一个原因,可能更严重<代码>BufferedInputStream(或
BufferedReader
)与网络套接字一起使用时,如果在套接字上启用了超时,则可能会导致无法预知的故障。读取数据包时可能会发生超时。您将无法再访问传输到该点的数据-即使您知道存在一些非零字节数(请参阅
java.net.SocketTimeoutException
,它是
java.io.InterruptedIOException
的子类,因此
ByTestTransferred
变量可用)

如果您想知道如何在读取时发生套接字超时,请考虑调用
read(bytes[])
方法,包含消息的原始数据包最终被拆分,但其中一个部分数据包延迟超过超时(或超时的剩余部分)。在实现
java.io.DataInput
(多字节值的任何读取,如
readLong()
readFully()
BufferedReader.readLine()
方法)的东西中再次包装时,这种情况会更频繁发生


请注意,
java.io.DataInputStream
对于具有超时的套接字流也是一个不好的候选,因为它在超时异常情况下也表现不好。

这似乎意味着标记和重置是唯一有用的东西
BufferedInputStream
在普通的
InputStream
上添加的内容PI是有意义的,但正如其他人所说,
BufferedInputStream
负责为您进行缓冲读取。从裸
FileInputStream
一次读取字节要比从封装在
BufferedInputStream
中的文件读取慢40倍。也就是说,返回
InputStream
,并保留您的方法签名。用户可以如果他们愿意,请包装。我同意从性能角度来看,最好将其包装在99.9%的情况下。但是,这确实减轻了消费者思考如何使用InputStream的责任。消费者的此类假设限制了可重用性。我认为,在超过0.1%的情况下,消费者不会阅读每次读取一个字节,而本身将使用某种缓冲区,在这种情况下,BufferedInputStream的开销是无用的。@Michael,我认为Peter的观点是,它将比99%的时间逐字节读取快,而不是99%的时间逐字节读取。关于BufferedInputStream和BufferedReader,这是城市神话。如果您得到读取超时,(i)您正在读取,因此内部缓冲区是空的,否则您将无法读取;(ii)在超时时间内没有数据到达。因此没有数据丢失。试试看。@EJP:您让我认真考虑了这一点,但我仍然认为这可能是一个问题。当缓冲流确实需要执行i/O时(填充缓冲区)然后,您就可以得到超时异常和内部变量,以跟踪缓冲区中有多少字节不会被更新。我已经尝试过测试这一点,但是,尽管我可以复制超时异常,但我似乎还无法复制
ByTestTransferred
为非零的情况。在此之前,我无法证明这一点这样或那样。[我丢失了DataInputStream和timeout的数据。]@EJP:也许这样,从套接字读取字节数组不会由于超时而导致部分读取缓冲区,然后
ByTestTransfered
永远不会为非零(否则BufferredInputStream将失败)。这也可能是一种情况,不同平台/供应商上的JVM实现可能会产生不同的结果-我刚刚用Sun/Oracle Java在Windows 7上进行了测试。但是BufferedInputStream不会“填充缓冲区”。请参阅Javadoc。它读取任何要读取的内容,就像任何其他读取一样,并返回该长度。具体地说,它从不阻塞两次。如果任何数据在超时时间内到达,则没有超时。相反,如果有超时,则