[英]Will FileChannel#write always write the whole buffer?
(這與(或者更確切地說是“相反”)有關。 如果有足夠的數據,FileChannel.read會讀取比指定的更少的字節嗎? )
TL; DR :
這總是會寫出整個緩沖區......
ByteBuffer bytes = ...;
fileOutputStream.getChannel().write(bytes);
...或者是否有必要使用這樣的循環:
ByteBuffer bytes = ...;
while (bytes.remaining() > 0)
{
fileOutputStream.getChannel().write(bytes);
}
?
由於另一個答案的評論 ,我想問一下,通過調用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類中跟蹤調用,但這些調用很快就會分散到不同的本機實現中 - 畢竟,這不應該是必要的......
不,不能保證write()會耗盡整個緩沖區。 文檔確實試圖建立實現應該一次性寫入所有字節的期望,但是它沒有做出任何承諾:
除非另有說明 , 否則只有在寫入所有r請求的字節后才會返回寫操作。 某些類型的通道(取決於它們的狀態[1] )可能只寫入一些字節,或者根本不寫 。
FileChannel.write()同樣為不完整的寫入留出了空間:
從給定緩沖區向該通道寫入一個字節序列。
除非通道處於附加模式,否則從該通道的當前文件位置開始寫入字節,在這種情況下,位置首先前進到文件的末尾。 如果需要,文件會增長以容納寫入的字節,然后使用實際寫入的字節數更新文件位置。 否則,此方法的行為與WritableByteChannel接口指定的完全相同。
因此,雖然文本暗示完整寫入是一般情況而不完整寫入是例外,但它為未來(能夠)遵守這種一般情況的替代/未來實現留下了空間。
正如您所指出的,這與read()的方法不同。 我想這是因為,在整合文檔時,所有已知和預期的實現都遵循執行完整寫入的一般情況。
[1]這可能是對非阻塞頻道的引用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.