Java=下载缓冲区未完全填满?冲洗/缓冲是如何工作的?
我想监控下载数据的进度。我想在传输了一定数量的数据后进行日志记录。我的代码:Java=下载缓冲区未完全填满?冲洗/缓冲是如何工作的?,java,stream,io,buffer,Java,Stream,Io,Buffer,我想监控下载数据的进度。我想在传输了一定数量的数据后进行日志记录。我的代码: int contentLength = 0; final int bufferSize = 1024*8; byte[] buffer = new byte[bufferSize]; int length = 0; while ( (length = bufferedInputStream.read(buffer) ) !=-1 ) { contentLength = contentLength+length
int contentLength = 0;
final int bufferSize = 1024*8;
byte[] buffer = new byte[bufferSize];
int length = 0;
while ( (length = bufferedInputStream.read(buffer) ) !=-1 ) {
contentLength = contentLength+length;
if ( (contentLength % (bufferSize*1024*4)) ==0 ) {
logger.debug(contentLength);
}
}
这似乎不起作用。似乎缓冲区并不总是满的,因此用作模的缓冲区大小的倍数不匹配
缓冲区不“满”真的很常见吗?这怎么会发生?bufer被“刷新”的内在逻辑是什么?Java是否等待s的特定时间来接收数据包,然后刷新(如果缓冲区未满)?任何关于它内部工作原理的信息都有助于理解它
(我不需要解决方案,我已经在其他地方实现了它,只是想知道缓冲区从未被完全读取是否很常见?我想知道为什么。)
非常感谢!
延斯不能保证缓冲区已满。这些是IO的细节。必须使用
read
的返回值来确定实际读取了多少数据。不能保证缓冲区已满。这些是IO的细节。您必须使用read
的返回值来确定实际读取了多少数据。当您可以读取(字节[,…)
API时,流将尝试填充缓冲区中分配的空间。但它并不总能填满它。当然,如果流中的内容用完了,它就无法填满整个空间。但也有其他原因。例如,流实现可以使用一些后台线程来获取数据。如果read调用被传递到操作系统,那么它一次可以读取一个数据块。如果流已缓冲,并且缓冲区仍有一些内容,则它可能只返回缓冲区中剩余的内容。当您可以读取(字节[…])API时,流将尝试填充缓冲区中分配的空间。但它并不总能填满它。当然,如果流中的内容用完了,它就无法填满整个空间。但也有其他原因。例如,流实现可以使用一些后台线程来获取数据。如果read调用被传递到操作系统,那么它一次可以读取一个数据块。如果流已缓冲,而缓冲区仍有一些内容,则它可能只返回缓冲区中剩余的内容。套接字上的读取操作通常不会完全填充缓冲区。发送方正在刷新不同长度的数据包。然后,它们通过应用程序层、操作系统层和网络层,这些应用程序层、操作系统层和网络层可能会将它们分割开来。典型的结果是部分缓冲区读取
我通常会调整读取缓冲区的大小以匹配作为最大大小的缓冲区,但我从不依赖于每次都将其填满
另外,您应该注意,在执行大容量读取(到字节数组中)时,使用
BufferedInputStream
效率很低。这只会增加从一个数组到另一个数组复制数据的开销。这也是上面提到的碎片的来源之一。套接字上的读取操作无法准确填充缓冲区是很常见的。发送方正在刷新不同长度的数据包。然后,它们通过应用程序层、操作系统层和网络层,这些应用程序层、操作系统层和网络层可能会将它们分割开来。典型的结果是部分缓冲区读取
我通常会调整读取缓冲区的大小以匹配作为最大大小的缓冲区,但我从不依赖于每次都将其填满
另外,您应该注意,在执行大容量读取(到字节数组中)时,使用
BufferedInputStream
效率很低。这只会增加从一个数组到另一个数组复制数据的开销。它也是上述碎片的来源之一。这实际上取决于您使用的实际InputStream
,归结为“操作系统如何处理read()
调用”
在大多数现代操作系统上,basicread
调用的作用是相同的:它尝试读取所请求的数据,但可能会提前停止
当缓冲区大于文件系统的预读缓冲区时,很容易发生这种情况。或者,当您从网络连接读取数据时,只有几个数据包到达
有些设备具有很好的预测性能(从文件系统读取的数据往往会完全填满提供的缓冲区(如果缓冲区不太大的话),从网络读取的数据往往会让缓冲区填满一半)。但你不能以这种或那种方式依赖它
因此:是的,这很容易发生。这实际上取决于您使用的实际
InputStream
,归结为“操作系统如何处理read()
调用”
在大多数现代操作系统上,basicread
调用的作用是相同的:它尝试读取所请求的数据,但可能会提前停止
当缓冲区大于文件系统的预读缓冲区时,很容易发生这种情况。或者,当您从网络连接读取数据时,只有几个数据包到达
有些设备具有很好的预测性能(从文件系统读取的数据往往会完全填满提供的缓冲区(如果缓冲区不太大的话),从网络读取的数据往往会让缓冲区填满一半)。但你不能以这种或那种方式依赖它
所以:是的,这很容易发生