简体   繁体   English

Java:使用FileChannel写入文件会使文件缩小吗?

[英]Java: Writing with FileChannel to a file make the file shrink?

I tried to write specific bytes to certain position of a file using FileChannel. 我试图使用FileChannel将特定字节写入文件的特定位置。 But actually the file shrink to the last position where I write change. 但是实际上文件缩小到了我写更改的最后位置。 I do it like this: 我这样做是这样的:

    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");

and this is the output I get: 这是我得到的输出:

3670KB
Write 1KB of data
1025KB

Can anybody tell me where it goes wrong?? 谁能告诉我哪里出了问题?

You're missing the FileOutputStream constructor which allows to append to the file. 您缺少允许附加到文件的FileOutputStream构造函数 If you create it as above, you overwrite the content of the file. 如果按上述方式创建,则会覆盖文件的内容。

try to use your FileOutputStream in append mode and avoid specifing current channel position: 尝试在附加模式下使用FileOutputStream并避免指定当前通道位置:

new FileOutputStream(path.toFile(), true)

upd. UPD。 didn't see the prevoius answer 没有看到prevoius的答案

FileOutputStream truncates the file to zero length when not in append mode. 如果不在附加模式下,FileOutputStream会将文件截断为零长度。 It does not overwrite a file's contents so much as it throws away the contents and starts over. 它不会覆盖文件的内容,而是会丢弃内容并重新开始。 You can verify this by calling chan.size() after creating the channel, which will give you 0. [1] 您可以在创建通道后通过调用chan.size()进行验证,这将为您提供0。 [1]

FileChannels can be advanced past the end of a file and told to write there; 可以将FileChannels推进到文件末尾并告知在其中写入; this causes the file size to increase to position + bytes_written (emphasis mine): 这导致文件大小增加到position + bytes_write(重点是我的):

Setting the position to a value that is greater than the current size is legal but does not change the size of the entity. 将头寸设置为大于当前大小的值是合法的,但不会更改实体的大小。 [..] A later attempt to write bytes at such a position will cause the entity to grow to accommodate the new bytes ; [..] 以后尝试在此位置写入字节将导致实体增长以容纳新的字节 the values of any bytes between the previous end-of-file and the newly-written bytes are unspecified. 未指定前一个文件末尾与新写入的字节之间的任何字节的值。

So while it looks like the FileChannel is cutting off your file after writing, it is the FileOutputStream truncating to 0 length, and then the FileChannel expanding it again. 因此,尽管看起来FileChannel在写入后正在切断文件,但FileOutputStream会截断为0的长度,然后FileChannel再次将其扩展。

To prevent this from happening, avoid using a FileOutputStream to create a channel. 为防止这种情况发生,请避免使用FileOutputStream创建通道。 You have a Path, so you can call Files.newByteChannel or FileChannel.open : 您具有路径,因此可以调用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] Note that programs outside the JVM, such as a file explorer, may not indicate this until you flush or close the stream. [1]请注意,除非刷新或关闭流,否则JVM外部的程序(例如文件浏览器)可能不会表明这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java FileChannel 不断锁定文件 - Java FileChannel keeps locking file 为什么 BufferedWriter 没有通过打开的 FileChannel 写入文件? - Why BufferedWriter is not writing into the file over the opened FileChannel? 使用NIO FileChannel将ByteArrayOutputStream的内容写入文件 - Writing contents of ByteArrayOutputStream to a file using NIO FileChannel 使用java.nio.FileChannel从两个不同的JVM同时写入文本文件和从中读取文本文件 - Writing to and reading from a text file using java.nio.FileChannel from two different JVMs concurrently 从FileChannel(Java NIO)读取GZIP文件 - Reading a GZIP file from a FileChannel (Java NIO) 使用FileChannel从文件中读取Java - Java Reading from a File using FileChannel 使用java FileChannel复制文件并追加文件末尾,但是终端卡住了 - using java FileChannel copy file and append the end of file, but the terminal stuck Java FileChannel.size()vs File.length() - 在FileChannel.truncate()之后 - Java FileChannel.size() vs File.length() - After FileChannel.truncate() 使用java FileChannel FileLock防止文件写入但允许读取 - using java FileChannel FileLock to prevent file writes but allow reads Java FileChannel.size()与File.length() - Java FileChannel.size() vs File.length()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM