如何每'x'秒将一行写入文件末尾

  • 本文关键字:一行 文件 何每 java
  • 更新时间 :
  • 英文 :


我试图每 5 秒连续向文件写入一行。因此,假设我有一个String = Hello world并且我运行了15秒的代码,我的输出应该是一个包含数据的文件

Hello World
Hello World
Hello world

到目前为止,我所拥有的是,我的文件只包含一行Hello World,而不是所需的 3 行。

到目前为止,我的代码如下所示:

public class MyFileWriter {
public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1000);
ses.scheduleAtFixedRate(new Runnable() {
public void run() {
FileWriter fw = null;
try {
fw = new FileWriter("Test5.txt");
} catch (IOException e1) {
e1.printStackTrace();
}
try {
fw.write("Hello World");
} catch (IOException e) {
e.printStackTrace();
}
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}, 0, 5, TimeUnit.SECONDS);
}
}

让我感到困惑的是,如果我将方法run更改为仅打印出Hello World而不是将其写入文件,它将每 5 秒打印一次,因此错误必须在于我如何编写它。我认为出于某种原因,它只是一遍又一遍地在第一行写Hello World

这么小的片段,这么多问题。

  1. 您正在覆盖模式下打开文件,因此每 5 秒一次,您将覆盖前一行Hello,并用一行新的Hello。您希望在追加模式下打开它。

  2. 永远不要使用"默认字符集编码"写入文件。这是一种有趣的表达方式"你永远不想要的东西"。解决所有这些问题的简单方法是不要使用此过时的API。请改用java.nio.file

  3. 您没有正确保护资源。使用试用资源(在这一点上,这是一个已有 10 年历史的 Java 功能。您正在浏览一些教程,找到一些更好的教程:P)

  4. 您的异常处理一言以蔽之,令人遗憾。如果此文件有问题,则每个错误将获得 3 次打印(将触发 3 个异常中的每一个)。作为一般规则,e.printStackTrace();是你永远不应该写的东西。当发生错误时,你[A]扔掉了很多有用的信息,[B]将其转储到syserr,这很少是一个合适的地方,最糟糕的是[C]你的代码只是继续运行,即使显然发生了一些你没有预料到的事情,因此,你不可能声称你的代码知道现在该怎么做。然而你继续前进。通常,如果您不知道如何处理错误,最好的选择是将其向前抛出(将throws X添加到方法声明中)。如果无法执行此操作,请包装异常(throw new RuntimeException(e);- 或特别是对于 IOExceptions,throw new UncheckedIOException(e);)。更新您的 IDE。另外,不要写 3 个捕获块,将它们组合在一起。

让我们解决所有这些问题:

public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1000);
Path path = Paths.get("Test5.txt");
ses.scheduleAtFixedRate(() -> {
try {
// The new API defaults to UTF_8 instead of 'system encoding'.
Files.write(path, List.of("Hello World"), StandardOpenOption.APPEND);
} catch (IOException e) {
throw new UncheckedIOException(e);
} // EDIT: I forgot this brace before.
}, 0, 5, TimeUnit.SECONDS);
}

这看起来简单多了,不是吗?

注意:现在不需要试用资源,因为我们只需调用一次性打开、写入和关闭的write,因此不需要尝试。

在每次迭代中,您都会使用FileWriter重新打开文件。默认情况下,它从文件的开头开始写入,因此始终使用相同的"Hello World"字符串覆盖其内容。

如果要将该句子添加到末尾,则需要在实例化FileWriter时设置"附加"选项。每次还要附加一个行分隔符:

public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1000);
ses.scheduleAtFixedRate(new Runnable() {
public void run() {
FileWriter fw = null;
try {
fw = new FileWriter("Test5.txt", true);
} catch (IOException e1) {
e1.printStackTrace();
}
try {
fw.write("Hello World");
fw.write(System.lineSeparator());
} catch (IOException e) {
e.printStackTrace();
}
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}, 0, 5, TimeUnit.SECONDS);
}

最新更新