使用带 append = false 的 FileOutputStream 时如何避免间歇性空行?
How to avoid intermittent empty lines when using FileOutputStream with append = false?
以下代码有时会使 random.txt
文件没有内容:
final Random rand = new Random();
while (true) {
try (FileOutputStream fos = new FileOutputStream("random.txt", false);
PrintWriter pw = new PrintWriter(fos, true)) {
pw.println(rand.nextLong());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
这可以使用 tail
来验证:
$ tail -f random.txt
511109499422519327
-4120669548002912852
-6691981558077108749
-3630360891256027458
2917713483009724854
-5999569794311404435
-7616466037397807657
6997723694593334477
-7350203015863330163
1355067773463270538
-8140835511024500423
-2536681669468724500
-2926317178660145957
-6983787629710676243
7119127016459332336
7186294589323134873
-8389505833590104437
197327637272321424
-1458700265861408851
5685819798785563231
4060059342974359248
215297222019419003
2913123181036087590
-5940005294121482941
5658270253202816998
如您所见,tail
的输出中有两个空白。发生这种情况是因为 FileOutputStream(fileName, false)
首先截断文件,然后向其中写入新数据。
因此,如果 tail
刚好在文件被截断时正在读取文件内容,则会显示一个空行。
除了使用涉及多个文件等的技术之外,有没有办法确保 截断和写入 操作自动发生?
Other than using techniques that involve multiple files, etc. is there a way to make sure the truncation and write operations happen atomically?
没有。在基本级别,截断和文件写入是两个独立的系统调用,OS 没有提供将两个系统调用组合成原子操作(或事务)的方法。
如果您的目的是为 tail -f
找到一个边缘案例,那么您就成功了。否则,可能有更好/更有效的方法来做你在这里想做的事情......比如写入管道,或附加到文件。如果有一些特殊原因需要这样做,请考虑过滤掉空白行。
实际上,我担心这里可能存在比偶尔出现的空行更严重的问题。如果 Java 程序在 tail
读取最后一行之前截断文件,您也可能 丢失非空行 。 (尝试将 rand.nextLong()
替换为递增计数器的值......看看您是否在 tail
输出中看到所有数字。)
以下代码有时会使 random.txt
文件没有内容:
final Random rand = new Random();
while (true) {
try (FileOutputStream fos = new FileOutputStream("random.txt", false);
PrintWriter pw = new PrintWriter(fos, true)) {
pw.println(rand.nextLong());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
这可以使用 tail
来验证:
$ tail -f random.txt
511109499422519327
-4120669548002912852
-6691981558077108749
-3630360891256027458
2917713483009724854
-5999569794311404435
-7616466037397807657
6997723694593334477
-7350203015863330163
1355067773463270538
-8140835511024500423
-2536681669468724500
-2926317178660145957
-6983787629710676243
7119127016459332336
7186294589323134873
-8389505833590104437
197327637272321424
-1458700265861408851
5685819798785563231
4060059342974359248
215297222019419003
2913123181036087590
-5940005294121482941
5658270253202816998
如您所见,tail
的输出中有两个空白。发生这种情况是因为 FileOutputStream(fileName, false)
首先截断文件,然后向其中写入新数据。
因此,如果 tail
刚好在文件被截断时正在读取文件内容,则会显示一个空行。
除了使用涉及多个文件等的技术之外,有没有办法确保 截断和写入 操作自动发生?
Other than using techniques that involve multiple files, etc. is there a way to make sure the truncation and write operations happen atomically?
没有。在基本级别,截断和文件写入是两个独立的系统调用,OS 没有提供将两个系统调用组合成原子操作(或事务)的方法。
如果您的目的是为 tail -f
找到一个边缘案例,那么您就成功了。否则,可能有更好/更有效的方法来做你在这里想做的事情......比如写入管道,或附加到文件。如果有一些特殊原因需要这样做,请考虑过滤掉空白行。
实际上,我担心这里可能存在比偶尔出现的空行更严重的问题。如果 Java 程序在 tail
读取最后一行之前截断文件,您也可能 丢失非空行 。 (尝试将 rand.nextLong()
替换为递增计数器的值......看看您是否在 tail
输出中看到所有数字。)