这与如果有足够的数据,FileChannel.read是否会读取少于指定数量的字节?相关(或者说是“相反”的)。
TL;DR:
...或者需要像这样使用循环吗:
由于另一个答案中的评论,我想问一下是否有关于通过调用{{link2:
仅供参考:文档中写道:
尝试将最多r个字节写入通道,其中r是在调用此方法时缓冲区中剩余的字节数,即src.remaining()。
假设写入长度为n的字节序列,其中0 <= n <= r。这个字节序列将从缓冲区的索引p处开始传输,其中p是在调用此方法时缓冲区的位置; 最后一个写入的字节的索引将是p + n - 1。返回后,缓冲区的位置将等于p + n;其限制没有改变。
除非另有说明,否则写操作仅在写入所有r个请求的字节后才会返回。某些类型的通道(取决于它们的状态)可能只写入一些字节或可能根本不写入。例如,处于非阻塞模式的套接字通道不能写入超出套接字输出缓冲区可用空间的字节。
此方法可以随时调用。但是,如果另一个线程已经启动了对此通道的写入操作,则对此方法的调用将被阻塞,直到第一个操作完成。
参数: src-要检索字节的缓冲区
返回值:写入的字节数,可能为零
在关于从
“读操作可能无法填充缓冲区,事实上它可能根本没有读取任何字节。”
相比之下,write方法的文档则是这样说的:
“除非另有说明,否则写操作将仅在写入所有 r 请求字节后才返回。某些类型的通道(依赖于它们的状态)可能仅写入其中一些字节或可能根本没有写入。”
对我来说,这意味着
从我对文件大小高达80 MB的测试中看来,写操作总是一次性写入整个缓冲区。但当然,这只是一个测试,并不足以得出深刻的结论。我尝试跟踪相关OpenJDK类中的调用,但这些很快就分散到不同的本地实现中 - 毕竟,这并不是必要的...
这是否总是写入整个缓冲区...
ByteBuffer bytes = ...;
fileOutputStream.getChannel().write(bytes);
...或者需要像这样使用循环吗:
ByteBuffer bytes = ...;
while (bytes.remaining() > 0)
{
fileOutputStream.getChannel().write(bytes);
}
?
由于另一个答案中的评论,我想问一下是否有关于通过调用{{link2:
FileChannel#write(ByteBuffer)
}}将Buffer
写入FileChannel
的行为的任何保证。
仅供参考:文档中写道:
从给定的缓冲区向此通道写入一系列字节。
除非通道处于追加模式,否则从当前文件位置开始写入字节;如果通道处于追加模式,则首先将位置推进到文件末尾。必要时增加文件大小以容纳写入的字节,然后使用实际写入的字节数更新文件位置。否则,此方法的行为与 WritableByteChannel 接口指定的完全相同。
覆盖方法 WritableByteChannel#write(ByteBuffer)
的文档如下:
尝试将最多r个字节写入通道,其中r是在调用此方法时缓冲区中剩余的字节数,即src.remaining()。
假设写入长度为n的字节序列,其中0 <= n <= r。这个字节序列将从缓冲区的索引p处开始传输,其中p是在调用此方法时缓冲区的位置; 最后一个写入的字节的索引将是p + n - 1。返回后,缓冲区的位置将等于p + n;其限制没有改变。
除非另有说明,否则写操作仅在写入所有r个请求的字节后才会返回。某些类型的通道(取决于它们的状态)可能只写入一些字节或可能根本不写入。例如,处于非阻塞模式的套接字通道不能写入超出套接字输出缓冲区可用空间的字节。
此方法可以随时调用。但是,如果另一个线程已经启动了对此通道的写入操作,则对此方法的调用将被阻塞,直到第一个操作完成。
参数: src-要检索字节的缓冲区
返回值:写入的字节数,可能为零
在关于从
FileChannel
中读取的问题中,评论中有一些关于文档精确措辞和解释的讨论。我认为文档的关键差异在于对read方法的描述说:“读操作可能无法填充缓冲区,事实上它可能根本没有读取任何字节。”
相比之下,write方法的文档则是这样说的:
“除非另有说明,否则写操作将仅在写入所有 r 请求字节后才返回。某些类型的通道(依赖于它们的状态)可能仅写入其中一些字节或可能根本没有写入。”
对我来说,这意味着
FileChannel
上的写操作只有在所有字节都被写入后才会返回,因为文档没有另外说明(除了返回值可能为 0,但这显然是覆盖的方法产生的)。从我对文件大小高达80 MB的测试中看来,写操作总是一次性写入整个缓冲区。但当然,这只是一个测试,并不足以得出深刻的结论。我尝试跟踪相关OpenJDK类中的调用,但这些很快就分散到不同的本地实现中 - 毕竟,这并不是必要的...
FileChannel
情况,它并没有明确说明它可能在写入所有请求的字节之前返回。 (是的,我看到返回值被称为“实际写入的字节数”,但它并没有说这可能少于请求的数量)。如果怀疑,一个人可能需要假设它不会写入所有字节。 - Marco13