有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

stream Java=下载缓冲区未满?冲洗/缓冲是如何工作的?

我想监控下载数据的进度。我想在传输了一定数量的数据后进行日志记录。我的代码:

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的特定时间来接收数据包,然后刷新(如果缓冲区未满)?任何关于它内部工作原理的信息都有助于理解它

(我不需要解决方案,我已经在其他地方实现了它,只是想知道缓冲区从未被完全读取是否很常见?我想知道为什么。)

非常感谢! 延斯


共 (4) 个答案

  1. # 1 楼答案

    不能保证缓冲区会满。这些是IO的细节。必须使用返回值read来确定实际读取了多少数据

  2. # 2 楼答案

    套接字上的读取操作无法准确填充缓冲区是很常见的。发送者正在刷新不同长度的数据包。然后,它们通过应用程序层、操作系统层和网络层,这些应用程序层、操作系统层和网络层可能会将它们分割开来。典型的结果是部分缓冲区读取

    我通常会调整读取缓冲区的大小,以匹配作为最大大小的socket's read buffer,,但我从不指望每次都能填满它

    另外,您应该注意,在执行大容量读取(到字节数组中)时,使用BufferedInputStream效率很低。这只会增加从一个数组到另一个数组复制数据的开销。它也是上述碎片化的来源之一

  3. # 3 楼答案

    这实际上取决于实际使用的InputStream,归结起来就是“操作系统如何处理read()调用”

    在大多数现代操作系统上,基本的read调用做同样的事情:它尝试读取所请求的数据,但可能会提前停止

    当缓冲区大于文件系统的预读缓冲区时,很容易发生这种情况。或者当你从网络连接中读取数据时,只有几个数据包到达

    有些设备具有很好的预测性能(从文件系统读取时,如果缓冲区不是很大,则趋向于将其完全填满,从网络读取时,缓冲区会更频繁地被填满一半)。但你不能以这种或那种方式依赖它

    所以:是的,这很容易发生

  4. # 4 楼答案

    当您可以使用read(byte[], ...)API时,流将尝试填充缓冲区中分配的空间。但它并不总能填满它。当然,如果流中的内容用完了,就无法填满整个空间。但也有其他原因。例如,流实现可以使用一些后台线程来获取数据。如果read调用被传递到操作系统,那么它可能一次读取一个数据块。如果流被缓冲,而缓冲区仍然有一些内容,它可能只返回缓冲区中剩余的内容