【问题标题】:BufferedWriter writes partial lines despite flush()尽管有 flush(),BufferedWriter 仍会写入部分行
【发布时间】:2015-10-14 20:09:51
【问题描述】:

我正在追加一个简单的日志文件,其中每一行都是一个条目。不幸的是,在关闭时,通常会出现部分写入的行。代码如下所示:

private val out = java.nio.file.Files.newBufferedWriter(
  java.nio.file.Paths.get(file),
  java.nio.charset.StandardCharsets.UTF_8,
  java.nio.file.StandardOpenOption.APPEND,
  java.nio.file.StandardOpenOption.CREATE)

def write(s: String) = synchronized {
  out.write(s)
  out.newLine()
  out.flush()
}

(对不起 Scala。)

我不明白为什么文件中有部分行。我相信的默认缓冲区大小是 8 kB。条目更短(

我无法重现部分行 - 问题发生在客户端。但我几乎可以肯定他们只是向进程发送 SIGTERM 以将其关闭。

SLF4J/LogBack/Log4j 写入的日志文件永远不会有部分行。我究竟做错了什么?我查看了 Apache Commons IO,希望找到一个有保证的基于行的 Writer,但没有。

【问题讨论】:

    标签: java java-io


    【解决方案1】:

    如果您处理不当,SIGTERM 将停止您的程序,无论它在哪里。它可能在flush() 的中间。考虑自己处理SIGTERM,并在发生这种情况时彻底关闭。

    但是,请注意,部分行总是会出现。您的程序可能会在flush() 期间被杀死,操作系统可能会崩溃或可能会发生断电。您的程序应该(在开始时)能够处理不以换行符结尾的日志。

    我对你提到的日志编写器没有足够的了解,不知道他们如何避免部分行,也许其他人可以提供比我更好的答案。

    【讨论】:

    • 谢谢!我希望 JVM 会为我处理 SIGTERM,也许会关闭文件和其他东西。有没有办法在不自己从头开始编写的情况下进行设置?该程序现在能够处理所有损坏的输入,但我仍然希望尽可能减少损坏的输入。
    • 我认为日志是一个很好的观点——因为新的文件系统都是日志文件系统。他们在事务开始之前在日志中写入事务,之后事务开始。如果交易完成,日记帐分录将被删除。如果系统在重启后意外关闭,将检查日志并执行记录的事务,以免丢失。
    • 要处理 SIGTERM,您可能需要使用 JVM 关闭挂钩,如 this answer 中所述
    猜你喜欢
    • 2016-01-30
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 2023-03-14
    • 1970-01-01
    • 2018-07-07
    相关资源
    最近更新 更多