你如何决定用于InputStream.read()的byte []大小?

时间:2012-01-05 20:02:17

标签: java io inputstream

从InputStreams读取时,如何确定byte []的大小?

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与磁盘有什么不同呢?

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

5 个答案:

答案 0 :(得分:22)

大多数人使用2的大小。 如果缓冲区至少为512字节,则它没有太大区别(<20%)

对于网络,最佳大小可以是2 KB到8 KB(基础数据包大小通常高达~1.5 KB)对于磁盘访问,最快的大小可以是8K到64 KB。如果您使用8K或16K,则不会有问题。

注意网络下载,您可能会发现通常不使用整个缓冲区。对于99%的用例而言,浪费几KB并不重要。

答案 1 :(得分:3)

这主要取决于您拥有多少内存以及您希望读取多少数据。你不想经常阻止,所以考虑BenCole的答案;另一方面,如果处理速度低于实际读数,则不希望处理少量数据。

我个人尝试使用库并卸载为库作者选择缓冲区大小的任务。在那之后,我保证自己永远不会阅读库代码,因为它让我很生气。

答案 2 :(得分:3)

在那种情况下,我总是使用2的合理功率,在2K到16K的范围内。通常,不同的InputStream将具有不同的最佳值,但没有简单的方法来确定该值。

为了确定最佳值,您需要了解更多有关正在处理的InputStream的确切类型,以及为InputStream提供服务的硬件规范等内容。

担心这可能是过早优化的一个例子。

答案 3 :(得分:1)

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

  

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

答案 4 :(得分:0)

我还要说的是,如果从InputStream(而不是像FileChannelSocketChannel这样的ReadableByteChannel中读取),则不必担心,因为只要您将其包装在缓冲区大小为BufferedInputStream@Peter Lawrey's answer中:内部缓冲区将为您处理读取操作,因此您可以集中精力阅读所需的内容。

在这种情况下,缓冲区大小可能正是您要寻找的,我会将您重定向到ByteBuffer:从网络访问数据时为2-8KB,而从硬盘驱动器为32-64KB (一个“大块”磁盘)。

不过,当从ByteChannel进行读取时,您必须通过{{3}}进行缓冲,然后才能使用该值进行分配。