可能是一个简单的答案,但是我尝试阅读StandardOpenOption上的javadoc文档,但是我仍然不清楚当我说Files.write(..., ..., StandardOpenOption.WRITE, StandardOpenOption.CREATE); // Write A
根据一些本地测试,看起来如果文件已经存在,它将仍然覆盖该文件,因此上述文件和文件之间有什么区别Files.write(..., ..., StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); // Write 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
$