gur*_*ing 1 java nio file java-io
可能是一个简单的答案,但我尝试阅读有关 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)
Run Code Online (Sandbox Code Playgroud)
我刚刚创建了一个名为“foo”的新文件,其中包含字符串“AAAA”:
$ more foo
AAAA
$
Run Code Online (Sandbox Code Playgroud)
现在我将字符串“BB”写入文件,不带 StandardOpenOption.TRUNCATE_EXISTING选项:
jshell> Files.write(path, "BB".getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE)
Run Code Online (Sandbox Code Playgroud)
只有前两个字符被覆盖,其他字符仍然存在:
$ more foo
BBAA
$
Run Code Online (Sandbox Code Playgroud)
现在我再次写入字符串“BB”,但我添加了 StandardOpenOption.TRUNCATE_EXISTING选项:
jshell> Files.write(path, "BB".getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
Run Code Online (Sandbox Code Playgroud)
StandardOpenOption.TRUNCATE_EXISTING该文件仅包含“BB”,因为其先前的内容在写入之前已被“擦除” :
$ more foo
BB
$
Run Code Online (Sandbox Code Playgroud)