2012-05-17 99 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