2012-05-17 61 views
2

我試圖使用FileChannel將特定字節寫入文件的某個位置。但實際上文件縮小到我寫更改的最後位置。我不喜歡這樣寫道:Java:使用FileChannel寫入文件會使文件縮小?

Path path = Paths.get("I://music - Copy.mp3"); 

    System.out.println(Files.size(path)/1024 + "KB"); 

    try (FileChannel chan = new FileOutputStream(path.toFile()).getChannel()) { 
     chan.position(1024 * 1024); 

     ByteBuffer b = ByteBuffer.allocate(1024); 
     chan.write(b); 

     System.out.println("Write 1KB of data"); 
    } 

    System.out.println(Files.size(path)/1024 + "KB"); 

,這是輸出I得到:

3670KB 
Write 1KB of data 
1025KB 

任何人能告訴我在哪裏出了問題?

回答

1

FileOutputStream在不處於追加模式時將文件截斷爲零長度。它不會覆蓋文件的內容,因爲它會丟棄內容並重新開始。你可以通過調用chan.size()創建通道,這會給你以後驗證這個0.1 [1]

FileChannels可以提前過去文件的末尾,並告訴寫有;這將導致文件大小增加至位置+ bytes_written(重點煤礦):

位置設置爲大於當前大小是合法的,但不改變實體的大小的值。 [...] 稍後嘗試在這樣的位置寫入字節將導致實體增長以適應新的字節;前一個文件結束和新寫入的字節之間的任何字節值都是未指定的。

因此,雖然看起來FileChannel在寫入後將文件切斷,但它是FileOutputStream截斷爲0的長度,然後FileChannel再次將其擴展。

爲防止發生這種情況,請避免使用FileOutputStream創建通道。你有一個路徑,這樣你就可以調用Files.newByteChannelFileChannel.open

Path path = Paths.get("I://music - Copy.mp3"); 

System.out.println(Files.size(path)/1024 + "KB"); 

// pick either: 
try (FileChannel chan = FileChannel.open(path, StandardOpenOption.WRITE)) { 
try (SeekableByteChannel chan = Files.newByteChannel(path, StandardOpenOption.WRITE)) { 
    chan.position(1024 * 1024); 

    ByteBuffer b = ByteBuffer.allocate(1024); 
    chan.write(b); 

    System.out.println("Write 1KB of data"); 
} 

System.out.println(Files.size(path)/1024 + "KB"); 

[1]請注意,JVM,外部程序,如文件瀏覽器,可以不指示,直到你刷新或關閉流。

4

你錯過了FileOutputStream constructor它允許追加到文件。如果按上述方式創建它,則會覆蓋該文件的內容。

+0

我試了一下,得到的輸出大小增加了1 KB(3670KB-3671KB)。這不僅僅意味着它被寫入文件結尾而不是指定位置? – Henry

1

嘗試使用您的FileOutputStream追加模式,避免specifing電流通道位置:

new FileOutputStream(path.toFile(), true) 

UPD。沒有看到prevoius的答案

+0

定位頻道不是問題 - 我想你應該編輯它。 –

+0

我在這裏需要的是寫入字節到指定的位置。不追加它.. – Henry