【问题标题】:Output flles keep getting ovewritten in Java输出文件不断被 Java 覆盖
【发布时间】:2013-01-25 08:46:27
【问题描述】:

我尝试过使用 BufferWriter 格式以及 FileWriter 和 PrintWriter,每个都带有一个布尔 true 语句,但它们的行为就像我只是使用一个简单的新文件一样。每次程序运行结束时,我都会调用写入要附加的已保存数据的函数。最终发生的是它覆盖了最后保存的数据。我还有其他代码块也可以处理该文本文件,但重新格式化它们也无济于事。

//saves user information to "Users.txt" which will be called in the finally block after choice switch
public void writeUsers()
{
    try{

        File userFile = new File("Users.txt");
        PrintWriter output = new PrintWriter(userFile);
        for(User i: userList) {    
        output.append("Name:");    
        output.println(i.getrealName());
        output.append("UID:");
        output.println(i.getidName());
        output.append("Password:");
        output.println(i.getpassword());
        output.println(" ");
        }
        output.close();
        System.out.print("Information has been saved to Users.txt\n");


    }
    catch(FileNotFoundException fnf) {
        System.err.println("FileNotFoundException: File Users.txt does not exist " + fnf);
    }
    catch(IOException eyeoh) {
        System.err.println("IOException: Error writing to Users.txt " + eyeoh);
    }
} 

【问题讨论】:

    标签: java file text io append


    【解决方案1】:

    构造函数PrintWriter(File)默认截断输出文件。调用PrintWriter 的方法append() 并不意味着它改变了打开文件的模式。 append 的行为是 described 为:

    以 out.append(csq) 形式调用此方法的行为与调用完全相同

     out.write(csq.toString()) 
    

    在这里,您可以使用 PrintWriter 的构造函数,该构造函数接受 FileOutputStream 进行追加

    PrintWriter output = 
       new PrintWriter(new FileOutputStream(userFile, true /* append = true */)); 
    

    【讨论】:

      【解决方案2】:

      您必须在附加模式下创建PrintWriter。否则,当它第一次打开文件时,它会清除它。您可以使用以下命令以附加模式打开它:

      new PrintWriter(new FileWriter(userFile,true)) // the `true` argument opens it in append mode
      

      【讨论】:

        【解决方案3】:

        默认的 PrintWriter 会截断所有现有数据。正如其他答案所建议的那样,要追加您可以向构造函数添加一个“true”参数,表示“append = true”,

        但是,使用 java.nio.file.Files 和 java.nio.file.StandardOpenOption 可以更优雅地完成此操作,您可以在其中指定 StandardOpenOption.APPEND 而不是 StandardOpenOption.TRUNCATE_EXISTING 您还可以指定诸如 StandardOpenOption.CREATE 之类的内容,如果文件不存在则创建该文件。

        此外,请记住将 output.close() 语句放在 finally 块中,或使用 try-with-resources。否则,如果程序流程被中断(即抛出异常),output 将保持未关闭状态。我个人使用 try-with-resources,因为它不那么麻烦:只需声明所有资源,它们会自动为您关闭,无论程序流程是否中断。

        此外,作为一般提示,在您的 catch 块中打印或传递实际的 Exception 对象,而不仅仅是“自定义字符串”,以免丢失 Exception 抛出的原始内容。然后,您可以将它与您还想打印的任何字符串连接起来。

        try(BufferedWriter bufWriter =
                Files.newBufferedWriter(Paths.get("Users.txt"),
                    Charset.forName("UTF8"),
                    StandardOpenOption.WRITE, 
                    StandardOpenOption.APPEND, //Makes this BufferedWriter append to the file, not truncate
                    StandardOpenOption.CREATE);
            PrintWriter output = new PrintWriter(bufWriter, true);)
        { 
        
            output.println("Text to be appended.");
        
        }catch(FileNotFoundException e){
            System.err.println(e + "Custom string");
        }catch(IOException e){
            System.err.println(e + "Something eyeoh occurred...");
        }
        

        这使用 try-with-resources 语句来声明和创建一个使用java.nio.file.FilesBufferedWriter,它接受StandardOpenOption 参数和一个自动刷新PrintWriter(在构造函数中用“true”表示)来自结果BufferedWriterPrintWriterprintln()方法,然后可以调用写入文件。

        此代码中使用的StandardOpenOption参数:打开文件写入,仅追加到文件,如果文件不存在则创建文件。

        Paths.get("path here") 可以替换为 new File("path here").toPath(),如果您只使用 File 对象(即,如果您使用的是 JFileChooser.getSelectedFile()) 并且可以修改Charset.forName("charset name") 以适应所需的Charset

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-11-19
          • 1970-01-01
          • 2014-06-07
          • 1970-01-01
          • 2018-09-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多