FileChannel#write总是写入整个缓冲区吗?

时间:2015-04-29 13:47:02

标签: java filechannel

(这与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的行为有任何保证。< / p>

仅供参考:文档说

  

从给定的缓冲区向该通道写入一个字节序列。

     

从该通道的当前文件位置开始写入字节,除非通道处于追加模式,在这种情况下,位置首先前进到文件的末尾。如果需要,文件会增长以容纳写入的字节,然后使用实际写入的字节数更新文件位置。否则,此方法的行为与WritableByteChannel接口指定的完全相同。

以及重写方法的文档WritableByteChannel#write(ByteBuffer)

  

从给定的缓冲区向该通道写入一个字节序列。

     

尝试向通道写入最多r个字节,其中r是缓冲区中剩余的字节数,即src.remaining(),此时调用此方法。

     

假设写入长度为n的字节序列,其中0 <= n <= r。该字节序列将从索引p开始从缓冲区传输,其中p是调用此方法时缓冲区的位置;写入的最后一个字节的索引将是p + n - 1.返回时,缓冲区的位置将等于p + n;它的限制不会改变。

     

除非另有说明,否则只有在写入所有r请求的字节后才会返回写操作。某些类型的通道(取决于它们的状态)可能只写入一些字节或者根本不写。例如,处于非阻塞模式的套接字通道不能再写入套接字输出缓冲区中可用的字节数。

     

可以随时调用此方法。但是,如果另一个线程已经在此通道上启动了写操作,则此方法的调用将阻塞,直到第一个操作完成。

     

参数:   src - 要从中检索字节的缓冲区

     

返回:写入的字节数,可能为零

在上面提到的FileChannel中关于阅读的问题中,评论中有一些关于本文档的准确措辞和解释的讨论。我认为文档中的关键区别在于,对于读取方法,文档说

  

读操作可能不会填充缓冲区,实际上它根本不会读取任何字节。

与此相反,方法的文档说

  

除非另有说明,否则只有在写入所有r请求的字节后才会返回写操作。某些类型的通道(取决于它们的状态)可能只写入一些字节或者根本不写。

对我来说,这意味着FileChannel 上的写操作只会在写完所有字节后返回,因为文档中没有另外指定(语句除外)返回值可能为0,但这显然是来自重写方法的工件)

从我的文件大小高达80 MB(!)的测试中,写操作总是一次写入整个缓冲区。但当然,这只是一个考验,并不足以作出深刻的陈述。我试图跟踪related OpenJDK classes中的调用,但这些调用很快就会分散到不同的本机实现中 - 毕竟,这不应该是必要的......

1 个答案:

答案 0 :(得分:2)

不,不能保证write()会耗尽整个缓冲区。文档确实尝试建立实现应该一次性写入所有字节的期望,但是它没有做出任何承诺:

  

除非另有说明,否则只有在写入所有r请求的字节后才会返回写操作。某些类型的通道,取决于它们的状态 [1] ,可能只写一些字节或者根本不写。

FileChannel.write()同样为不完整的写入留下了空间:

  

从给定的缓冲区向该通道写入一个字节序列。

     

从该通道的当前文件位置开始写入字节,除非通道处于追加模式,在这种情况下,位置首先前进到文件的末尾。如有必要,文件会增长以容纳写入的字节,然后使用实际写入的字节数更新文件位置。否则,此方法的行为与WritableByteChannel接口指定的完全相同。

因此,尽管文本暗示完整写入是一般情况而不完整写入是例外,但它为未来(能够)遵守这种一般情况的替代/未来实现留下了空间。< / p>

正如您所指出的,这与read()的方法不同。我想这是因为,在整合文档时,所有已知和预期的实现都遵循执行完整写入的一般情况。

[1]这可能是对非阻塞频道的引用。