Java 快速写入文件-有时文件是空的

Java 快速写入文件-有时文件是空的,java,file-io,Java,File Io,修改 经过一些调查,我可以用这个测试代码重现我的问题。问题与线程无关,但与快速写入无关: public static void main(String[] args) { String text = "Testing fast writing in file"; for (int i = 0 ; i < 100000 ; i++) { BufferedWriter bw = null; try { bw = new B

修改 经过一些调查,我可以用这个测试代码重现我的问题。问题与线程无关,但与快速写入无关:

public static void main(String[] args) {
    String text = "Testing fast writing in file";
    for (int i = 0 ; i < 100000 ; i++) {
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(new File("temp.txt")));
            bw.write(text);
        } catch(Throwable t) { // Ensure there is no throwable for the test
            System.err.println(t.getMessage());
        } finally {
            if(bw != null) {
                try {
                    bw.close();
                } catch (IOException ioe) {
                    System.err.println(ioe.getMessage());
                }
            }
        }
    }
}
问题是,有时当我查看文件时,它是空的(myObject从不为空也不为null)。如果服务崩溃,此文件允许我们稍后恢复某些作业

考虑到编组过程可能很长,我首先在缓冲区中写入,然后写入文件:

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(8192);
marshaller.marshal(myObject, outputStream);
String result = outputStream.toString();
if (result != null && !result.isEmpty()) {
  BufferedWriter bw = null;
  try {
    bw = new BufferedWriter(new FileWriter(myFile));
    bw.write(result);
    bw.flush(); // I know close() should do that, but I tried too
  } catch(IOException ioe) {
    ...
  } finally {
    ... close the bw
  }
问题仍然存在。因此,我还尝试将
synchronized
添加到方法中(唯一用于写入文件的方法),但我遇到了同样的问题

最后,我还尝试保留一个
静态布尔值
,以了解我是否正在编写:

if (!processing) {
  processing = true;
  try {
  Marshaller marshaller = jaxbContext.createMarshaller();
  ...
  ... close file writer
  processing = false;
}

同样,避免出现空文件的最佳方法是什么?我现在对此有点困惑。

我认为您误解了FileWriter的用法。在所示的示例中,您可以在同一文件中同时使用多个线程进行写入,但FileWriter的工作方式是,它会重置文件的内容,除非您明确告诉它要追加

FileWriter fw = new FileWriter(new File("temp.txt"), true);

如果不想追加,则需要确保只有一个线程正在写入文件。此外,检查看似空的文件时,可能正好在写入程序开始执行其it's任务之前,文件被清除的同时。

以下是我目前的情况: 写入临时文件,一旦完成,重命名它。 最后一个文件总是被填写的

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(myObject, myFileTmp);

if (myFileTmp.exists() && myFileTmp.length() > 0) {
  myFile.delete();
  myFileTmp.renameTo(myFile);
}

然后我修改了代码,只让一个线程写入该文件。

除了空文件的问题外,如果多个线程独立地将XML文本写入同一个文件,您的预期输出是什么?@Pino嗯,其实并不重要,不管线程最后写入什么,都可以恢复。但最后我会同步所有东西。所以我的问题是,即使是同步的,我也会得到一些空文件。建议您查找丢失/丢弃/忽略的异常。@OldCurmudgeon我添加了一个-nice-
try{}catch(Throwable)
,但从来没有到过那里,一切正常。是NP++吗?也许是因为它无法读取文件。尝试检查文件大小而不是内容。我希望替换而不是追加
“可能恰好在写入程序开始执行其it任务之前文件被清除的同时”
是的,没错,这是我不想要的。
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(myObject, myFileTmp);

if (myFileTmp.exists() && myFileTmp.length() > 0) {
  myFile.delete();
  myFileTmp.renameTo(myFile);
}