何时使用 BufferedWriter.flush() 方法?

53
在一个Java程序(Java 1.5)中,我有一个包装了FileWriter的BufferedWriter,并且我调用write()很多次...生成的文件相当大...
在这个文件的行数中,有些是不完整的...
我需要每次写入时都调用flush()吗(但我怀疑这样做效率会低下),或者使用BufferedWriter的另一个方法或使用其他类...?
(由于我有大量的行要写入,因此我希望有一些非常高效的解决方法。) 什么时候是理想的“flushing”时机?(当我达到BufferedWriter的容量时)...
Init:
try {
  analysisOutput = new BufferedWriter(new FileWriter(
      "analysisResults", true));
  analysisOutput.newLine();
  analysisOutput.write("Processing File " + fileName + "\n");
} 
catch (FileNotFoundException ex) {
  ex.printStackTrace();
} 
catch (IOException ex) {
  ex.printStackTrace();
}

写作:

private void printAfterInfo(String toBeMoved,HashMap<String, Boolean> afterMap, Location location)
  throws IOException {
    if(afterMap != null) {
      for (Map.Entry<String, Boolean> map : afterMap.entrySet()) {
        if (toBeMoved == "Condition") {
          if (1 <= DEBUG)
            System.out.println("###" + toBeMoved + " " + location + " "
                + conditionalDefs.get(conditionalDefs.size() - 1)
                + " After " + map.getKey() + " "
                + map.getValue() + "\n");

          analysisOutput.write("###" + toBeMoved + " " + location + " "
              + conditionalDefs.get(conditionalDefs.size() - 1)
              + " After " + map.getKey() + " " + map.getValue()
              + "\n");
        } else {
          if (1 <= DEBUG)
            System.out.println("###" + toBeMoved + " " + location + " "
                + map.getKey() + " After " 
                + map.getValue() + "\n");
          if (conditionalDefs.size() > 0)
            analysisOutput.write("###" + toBeMoved + " " + location + " "
                + conditionalDefs.get(conditionalDefs.size() - 1) + " "
                + map.getKey() + " After " + map.getValue()
                + "\n");
          else
            analysisOutput.write("###" + toBeMoved + " " + location + " " + map.getKey() + " After " + map.getValue() + "\n");


        }
      }
    }

我刚刚发现那些不完整的行是在“处理文件”之前,所以当我从一个我要分析的文件切换到另一个文件时会出现这种情况...

结束:

dispatch(unit);

try {
  if (analysisOutput != null) {
    printFileInfo();
    analysisOutput.close();
  }
} 
catch (IOException ex) {
  ex.printStackTrace();
}
有时候,printFileInfo打印出的信息在结果文件中并没有显示...

1
如果有一些不完整,你是否有多个线程同时写入它?如果我没记错,BufferedWriter 不是线程安全的,所以这可能是一个解释,但它不必要“手动刷新”来腾出更多空间,它会自己处理。 - Kevin Anderson
如果您不确定您的问题是否清晰,请提供一个代码示例或输出示例来澄清。 - S.Lott
它实际上是线程安全的(尽管Writer装饰器在同意锁定哪个对象方面存在问题)。 - Tom Hawtin - tackline
如何确保这是线程安全的?我正在写入静态文件并使用make -j(我猜这是多线程的...) - LB40
我会在printFileInfo()方法中寻找错误。 - Skip Head
3个回答

103

BufferedWriter在填满其缓冲区时将自动刷新。来自BufferedWriter.write的文档:

通常,此方法将给定数组中的字符存储到此流的缓冲区中,根据需要刷新底层流的缓冲区

(强调是我的)

BufferedWriter的作用基本上是将许多小写操作合并为较少的大写操作,因为通常这样更有效(但编码时会更麻烦)。您不需要做任何特殊处理来使其正常工作,只需确保在完成后刷新它-调用close()将这样做并刷新/关闭底层写程序。

换句话说,放松一点 - 只需写入数据并关闭 :) 普通情况下,您通常只需要手动调用flush的时间是如果您真的非常需要数据立即写入磁盘。 (例如,如果您有一个永久记录器,则可能每隔一段时间需要刷新一次,以便查看日志的人无需等待缓冲区满了才能看到新的日志条目!)


3
已测试并批准。逐行编写10MB的数字,每行写完后进行清除缓存-需要7秒钟,不进行清除缓存-需要4秒钟。 - Kirill Karmazin

14

理想的刷新时机是在文件关闭之前,需要另一个程序读取已写入的数据。在许多情况下,这种情况是不会发生的。


即使 BufferedWriter 很大,我也不必在中间阶段执行它吗? - LB40
1
如果缓冲区填满,将会把其内容写入到磁盘。BufferedWriter API 被设计成可替换 FileWriter 的一种即插即用的方案,唯一不同的是在文件被关闭之前消耗数据。 - Dave

0
如果你有一个交替使用initprintAfterInfo的循环,我猜测你的问题是在创建新文件之前没有close你的写入器,而且最好只创建一次BufferedWriter并在所有处理结束后进行关闭。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接