java - 带/不带 TRUNCATE_EXISTING 的 StandardOpenOption.WRITE + StandardOpenOption.CREATE 之间的区别?

标签 java file nio java-io

可能是一个简单的答案,但我已经尝试阅读有关 StandardOpenOption 的 javadoc 文档,但我仍然不清楚当我说时会发生什么

Files.write(..., ..., StandardOpenOption.WRITE, StandardOpenOption.CREATE);//写一个

根据一些本地测试,看起来如果文件已经存在,这仍然会覆盖该文件,那么上面和上面有什么区别

Files.write(..., ..., StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);//写B

此外,我有一个带有两个线程的程序,可以从写入的文件中读取/写入。当我使用 Write B 时,我有时会遇到竞争条件,其中一个线程创建了该文件,而另一个线程在第一个线程正在读取时覆盖该文件,并且出现异常。但是当我使用 Write A 时,我永远不会遇到这种竞争条件。几乎就像它会先锁定文件一样?有人可以解释一下幕后发生了什么吗?

最佳答案

当您使用StandardOpenOption.TRUNCATE_EXISTING时如果文件任何写入之前已经存在,则文件的长度首先被“截断为0”:

$ jshell

jshell> import java.nio.file.*;

jshell> Path path = Paths.get("foo");
path ==> foo

jshell> Files.write(path, "AAAA".getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE)

我刚刚创建了一个名为“foo”的新文件,其中包含字符串“AAAA”:

$ more foo
AAAA
$

现在我将字符串“BB”写入文件没有 StandardOpenOption.TRUNCATE_EXISTING 选项:

jshell> Files.write(path, "BB".getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE)

只有前两个字符被覆盖,其他字符仍然存在:

$ more foo
BBAA
$

现在我再次写入字符串“BB”,但我添加 StandardOpenOption.TRUNCATE_EXISTING 选项:

jshell> Files.write(path, "BB".getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)

该文件仅包含“BB”,因为在写入之前其先前的内容已被 StandardOpenOption.TRUNCATE_EXISTING“删除”:

$ more foo
BB
$

关于java - 带/不带 TRUNCATE_EXISTING 的 StandardOpenOption.WRITE + StandardOpenOption.CREATE 之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62394352/

相关文章:

java - 在 Java 类中具有 super() 和不具有 super() 函数调用的构造函数有什么区别

java - 是否有自动删除发布版本调试方法的方法?

java - 是否可以检测内核生成 epoll 的时刻与 Sun JVM 读取它的时刻之间的时间差?

java - 如何删除 API 级别 >= 23 的文件或目录?

java - Java NIO 是否支持广播或多播?

Java NIO 服务器如何读取带/不带任何 header 的可变长度数据包

java - Tomcat 无法让 servlet 工作

java - Content-Length 分隔的消息正文过早结束(预期为 :

c - 如何在 Linux 上显示文件的最后修改时间

c - C 判断文件是否已被复制