从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与磁盘有什么不同呢?
非常感谢,我似乎无法在其他地方找到明确答案。
答案 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
(而不是像FileChannel
或SocketChannel
这样的ReadableByteChannel
中读取),则不必担心,因为只要您将其包装在缓冲区大小为BufferedInputStream
的@Peter Lawrey's answer中:内部缓冲区将为您处理读取操作,因此您可以集中精力阅读所需的内容。
在这种情况下,缓冲区大小可能正是您要寻找的,我会将您重定向到ByteBuffer
:从网络访问数据时为2-8KB,而从硬盘驱动器为32-64KB (一个“大块”磁盘)。
不过,当从ByteChannel
进行读取时,您必须通过{{3}}进行缓冲,然后才能使用该值进行分配。