如何决定InputStream.read()使用什么字节[]大小?

问题描述 投票:33回答:5

从InputStreams读取时,如何决定字节[]的大小?

int nRead;
byte[] data = new byte[16384]; // <-- this number is the one I'm wondering about

while ((nRead = is.read(data, 0, data.length)) != -1) {
  ...do something..
}

什么时候使用小的和大的?有什么区别?数字是否要以1024为增量?如果是来自网络的InputStream和磁盘的InputStream有什么区别吗?

非常感谢,我似乎在其他地方找不到明确的答案。

java io inputstream
5个回答
24
投票

大多数人使用2的幂数来决定大小,如果缓冲区至少是512字节,那就不会有太大的区别( < 20% )

对于网络来说,最佳的大小可以是2KB到8KB(底层数据包的大小通常可达约1.5KB)对于磁盘访问来说,最快的大小可以是8K到64KB。 如果你用8K或16K就不会有问题。

注意对于网络下载,你很可能会发现你通常不会使用整个缓冲区。 对于99%的用例来说,浪费几KB并没有什么大不了的。


4
投票

在这种情况下,我总是使用一个合理的2的幂,在2K到16K的范围内。 一般来说,不同的InputStreams会有不同的最佳值,但没有简单的方法来确定这个值。

为了确定最佳值,你需要更多地了解你所处理的InputStream的确切类型,以及服务于InputStream的硬件规格等。

担心这些可能是一种过早优化的情况。


3
投票

这主要取决于你有多少内存以及你期望读取多少数据。你不希望太频繁地阻塞,所以要考虑到 BenCole'的答案;另一方面,如果你的处理速度比实际读取速度慢,你也不想处理一小块数据。

我个人尽量使用库,并将选择缓冲区大小的任务卸载给库作者。之后,我答应自己永远不读库的代码,因为它让我疯狂。


0
投票

通过使用 available() 中的方法 InputStream 类。 来自Javadoc。

返回可以从这个输入流中读取(或跳过)的字节数,而不会被这个输入流的下一个方法的调用者阻塞。下一个调用者可能是同一个线程或或另一个线程。


0
投票

我还想说的是,如果从一个叫 InputStream (非来自 ReadableByteChannelFileChannelSocketChannel),你应该不会在意,只要你把它包装成一个。BufferedInputStream 正确的 "缓冲区大小:内部缓冲区将为你负责读取,所以你可以专注于读取你需要的部分。

在这种情况下,缓冲区的大小可能就是你要找的东西,我会把你转到 @Peter Lawrey的回答当数据从网络访问时,为2-8KB,当数据从硬盘访问时,为32-64KB(磁盘的 "块")。

当从硬盘读取数据时 ByteChannel 不过,你必须自己通过一个 ByteBuffer 你可以用这个值来分配。

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