personis
personis

Reputation: 1

Output flles keep getting ovewritten in Java

I've tried using BufferWriter format as well as FileWriter and PrintWriter each with a boolean true statement but they both behave the same as if I simply used a simple new File. Each time I get to the end of my program run, I call the function that writes the saved data to be appended. What ends up happening is that it overwrites the last saved data. I also have other code blocks that handle that text file as well and reformating them did nothing either.

//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);
    }
} 

Upvotes: 0

Views: 677

Answers (3)

icasdri
icasdri

Reputation: 106

PrintWriter by defualt truncates all existing data. To append you could, as other answers suggest, add a "true" argument to the constructor, which denotes "append = true,"

However, this is done more elegantly using java.nio.file.Files along with java.nio.file.StandardOpenOption, in which you can specify StandardOpenOption.APPEND as opposed to StandardOpenOption.TRUNCATE_EXISTING You can also specify things such as StandardOpenOption.CREATE which creates the file if it does not exist.

Additionally, remember to either place your output.close() statement in a finally block, or use try-with-resources. Otherwise if the flow of the program is interrupted (i.e. an Exception is thrown), output would remain unclosed. I personally use try-with-resources as it is less of a hassle: just declare all your resources, and they are closed automatically for you, whether or not the flow of the program is disrupted.

Also, as a general tip, print or pass the actual Exception object in your catch block, as opposed to just a "custom string" so as to not lose the original content of the Exception thrown. You can then concatenated that with whatever string you also want to print.

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...");
}

This uses a try-with-resources statement to declare and create a BufferedWriter using java.nio.file.Files, which accepts StandardOpenOption parameters, and an auto-flushing PrintWriter (denoted by "true" in the constructor) from the resultant BufferedWriter. PrintWriter's println() method, can then be called to write to the file.

The StandardOpenOption parameters used in this code: opens the file for writing, only appends to the file, and creates the file if it does not exist.

Paths.get("path here") can be replaced with new File("path here").toPath(), if you are working exclusively with File objects (i.e. if you are using JFileChooser.getSelectedFile()) And Charset.forName("charset name") can be modified to accommodate the desired Charset.

Upvotes: 1

Reimeus
Reimeus

Reputation: 159754

The constructor PrintWriter(File) truncates the output file by default. The fact that PrintWriter's method append() is called doesn't mean that it changes the mode of the file being opened. The behavior for append is described as:

An invocation of this method of the form out.append(csq) behaves in exactly the same way as the invocation

 out.write(csq.toString()) 

Here, you could use the constructor for PrintWriter that takes a FileOutputStream for appending

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

Upvotes: 2

Jeff Storey
Jeff Storey

Reputation: 57182

You have to create the PrintWriter in append mode. Otherwise, when it first opens the file, it will clear it out. You can open it in append mode using:

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

Upvotes: 1

Related Questions