【发布时间】:2015-07-08 20:30:01
【问题描述】:
(这与Would FileChannel.read read less bytes than specified if there's enough data? 相关(或更确切地说是“相反”)
TL;DR:
这是否总是写入整个缓冲区...
ByteBuffer bytes = ...;
fileOutputStream.getChannel().write(bytes);
...或者是否有必要使用这样的循环:
ByteBuffer bytes = ...;
while (bytes.remaining() > 0)
{
fileOutputStream.getChannel().write(bytes);
}
?
由于comment in another answer,我想问一下,通过调用FileChannel#write(ByteBuffer) 将Buffer 写入FileChannel 的行为是否有任何保证。
仅供参考:文档说
从给定的缓冲区将字节序列写入此通道。
字节从该通道的当前文件位置开始写入,除非通道处于追加模式,在这种情况下,该位置首先前进到文件末尾。如有必要,文件会增长以容纳写入的字节,然后使用实际写入的字节数更新文件位置。否则,此方法的行为与 WritableByteChannel 接口指定的完全相同。
以及覆盖方法的文档,WritableByteChannel#write(ByteBuffer) 说
从给定的缓冲区将字节序列写入此通道。
尝试向通道写入最多 r 个字节,其中 r 是在调用此方法时缓冲区中剩余的字节数,即 src.remaining()。
假设写入一个长度为 n 的字节序列,其中 0
除非另有说明,否则写入操作仅在写入所有 r 个请求字节后才会返回。某些类型的通道,取决于它们的状态,可能只写入一些字节,或者根本不写入。例如,处于非阻塞模式的套接字通道不能写入超过套接字输出缓冲区中空闲的字节数。
可以随时调用此方法。但是,如果另一个线程已经对该通道发起了写操作,则对该方法的调用将阻塞,直到第一个操作完成。
参数: src - 要从中检索字节的缓冲区
返回:写入的字节数,可能为零
在上述关于从FileChannel 中阅读的问题中,在 cmets 中已经对本文档的确切措辞和解释进行了一些讨论。我认为文档中的关键区别在于 read 方法,文档说
读取操作可能不会填满缓冲区,实际上它可能根本不会读取任何字节。
与此相反,write 方法的文档说
除非另有说明,否则写入操作仅在写入所有 r 个请求字节后才会返回。某些类型的通道,取决于它们的状态,可能只写入一些字节,或者根本不写入。
对我来说,这意味着对 FileChannel 的写操作将仅在写入所有字节后返回,因为文档中没有另外指定(除了声明返回值可能为 0,但这显然是被覆盖方法的产物)
根据我对最大 80 MB (!) 文件大小的测试,写操作总是 一次写入整个缓冲区。但当然,这只是一个测试,不足以做出深刻的陈述。我试图追踪related OpenJDK classes 中的调用,但这些调用很快就会分化为不同的原生实现——毕竟,这不应该是必要的......
【问题讨论】:
标签: java filechannel