How to append text to an existing file in Java?

1,140,091

Solution 1

Are you doing this for logging purposes? If so there are several libraries for this. Two of the most popular are Log4j and Logback.

Java 7+

For a one-time task, the Files class makes this easy:

try {
    Files.write(Paths.get("myfile.txt"), "the text".getBytes(), StandardOpenOption.APPEND);
}catch (IOException e) {
    //exception handling left as an exercise for the reader
}

Careful: The above approach will throw a NoSuchFileException if the file does not already exist. It also does not append a newline automatically (which you often want when appending to a text file). Another approach is to pass both CREATE and APPEND options, which will create the file first if it doesn't already exist:

private void write(final String s) throws IOException {
    Files.writeString(
        Path.of(System.getProperty("java.io.tmpdir"), "filename.txt"),
        s + System.lineSeparator(),
        CREATE, APPEND
    );
}

However, if you will be writing to the same file many times, the above snippets must open and close the file on the disk many times, which is a slow operation. In this case, a BufferedWriter is faster:

try(FileWriter fw = new FileWriter("myfile.txt", true);
    BufferedWriter bw = new BufferedWriter(fw);
    PrintWriter out = new PrintWriter(bw))
{
    out.println("the text");
    //more code
    out.println("more text");
    //more code
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}

Notes:

  • The second parameter to the FileWriter constructor will tell it to append to the file, rather than writing a new file. (If the file does not exist, it will be created.)
  • Using a BufferedWriter is recommended for an expensive writer (such as FileWriter).
  • Using a PrintWriter gives you access to println syntax that you're probably used to from System.out.
  • But the BufferedWriter and PrintWriter wrappers are not strictly necessary.

Older Java

try {
    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
    out.println("the text");
    out.close();
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}

Exception Handling

If you need robust exception handling for older Java, it gets very verbose:

FileWriter fw = null;
BufferedWriter bw = null;
PrintWriter out = null;
try {
    fw = new FileWriter("myfile.txt", true);
    bw = new BufferedWriter(fw);
    out = new PrintWriter(bw);
    out.println("the text");
    out.close();
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}
finally {
    try {
        if(out != null)
            out.close();
    } catch (IOException e) {
        //exception handling left as an exercise for the reader
    }
    try {
        if(bw != null)
            bw.close();
    } catch (IOException e) {
        //exception handling left as an exercise for the reader
    }
    try {
        if(fw != null)
            fw.close();
    } catch (IOException e) {
        //exception handling left as an exercise for the reader
    }
}

Solution 2

You can use fileWriter with a flag set to true , for appending.

try
{
    String filename= "MyFile.txt";
    FileWriter fw = new FileWriter(filename,true); //the true will append the new data
    fw.write("add a line\n");//appends the string to the file
    fw.close();
}
catch(IOException ioe)
{
    System.err.println("IOException: " + ioe.getMessage());
}

Solution 3

Shouldn't all of the answers here with try/catch blocks have the .close() pieces contained in a finally block?

Example for marked answer:

PrintWriter out = null;
try {
    out = new PrintWriter(new BufferedWriter(new FileWriter("writePath", true)));
    out.println("the text");
} catch (IOException e) {
    System.err.println(e);
} finally {
    if (out != null) {
        out.close();
    }
} 

Also, as of Java 7, you can use a try-with-resources statement. No finally block is required for closing the declared resource(s) because it is handled automatically, and is also less verbose:

try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("writePath", true)))) {
    out.println("the text");
} catch (IOException e) {
    System.err.println(e);
}

Solution 4

Using Apache Commons 2.1:

FileUtils.writeStringToFile(file, "String to append", true);

Solution 5

Slightly expanding on Kip's answer, here is a simple Java 7+ method to append a new line to a file, creating it if it doesn't already exist:

try {
    final Path path = Paths.get("path/to/filename.txt");
    Files.write(path, Arrays.asList("New line to append"), StandardCharsets.UTF_8,
        Files.exists(path) ? StandardOpenOption.APPEND : StandardOpenOption.CREATE);
} catch (final IOException ioe) {
    // Add your own exception handling...
}

Further notes:

  1. The above uses the Files.write overload that writes lines of text to a file (i.e. similar to a println command). To just write text to the end (i.e. similar to a print command), an alternative Files.write overload can be used, passing in a byte array (e.g. "mytext".getBytes(StandardCharsets.UTF_8)).

  2. The CREATE option will only work if the specified directory already exists - if it doesn't, a NoSuchFileException is thrown. If required, the following code could be added after setting path to create the directory structure:

    Path pathParent = path.getParent();
    if (!Files.exists(pathParent)) {
        Files.createDirectories(pathParent);
    }
    
Share:
1,140,091
flyingfromchina
Author by

flyingfromchina

Updated on January 16, 2021

Comments

  • flyingfromchina
    flyingfromchina over 3 years

    I need to append text repeatedly to an existing file in Java. How do I do that?

  • Alphaaa
    Alphaaa almost 11 years
    Oh, thank you. I was amused by the complexity of all other answers. I really do not get why people like to complicate their (developer) life.
  • Kip
    Kip over 10 years
    When out goes out of scope, it is automatically closed when it gets garbage-collected, right? In your example with the finally block, I think you actually need another nested try/catch around out.close() if I remember correctly. The Java 7 solution is pretty slick! (I haven't been doing any Java dev since Java 6, so I was unfamiliar with that change.)
  • Svetlin Zarev
    Svetlin Zarev over 10 years
    You should either use java7 try-with-resources or put the close() in a finally block, in order to make sure that the file is closed in case of exception
  • Svetlin Zarev
    Svetlin Zarev over 10 years
    Lets imagine that new BufferedWriter(...) throws an exception; Will the FileWriter be closed ? I guess that it will not be closed, because the close() method (in normal conditions) will be invoked on the out object, which int this case will not be initialized - so actually the close() method will not be invoked -> the file will be opened, but will not be closed. So IMHO the try statement should look like this try(FileWriter fw = new FileWriter("myFile.txt")){ Print writer = new ....//code goes here } And he should flush() the writer before exiting the try block!!!
  • Navin
    Navin almost 10 years
    @Kip Nope, going out-of-scope does nothing in Java. The file will get closed at some random time in the future. (probably when the program closes)
  • Emily L.
    Emily L. over 9 years
    Caution, the "Older java" example will not properly close the stream if an exception is thrown inside the try block.
  • Mahdi
    Mahdi over 9 years
    it's not work for me. in destination file, there is one "test" and many empty space
  • xehpuk
    xehpuk about 9 years
    This is horrible advice. You open a stream to the file 42 times instead of once.
  • dantuch
    dantuch about 9 years
    @xehpuk well, it depends. 42 is still ok, if it makes code much more readable. 42k wouldn't be acceptable.
  • Pshemo
    Pshemo about 9 years
    close should be placed in finally block just like shown in @etech's answer in case exception would be thrown between creation of FileWriter and invoking close.
  • Chetan Bhasin
    Chetan Bhasin about 9 years
    What are the imports required? Which library do these things use?
  • assylias
    assylias almost 9 years
    If you use Java 7+, then why not use a simple Files.write instead of a PrintWriter of a BufferedWriter of a FileWriter?
  • Vadzim
    Vadzim almost 9 years
    This answer fails to correctly handle exceptions. See @Emily's answer for proper way.
  • Vadzim
    Vadzim almost 9 years
    +1 for correct ARM with Java 7. Here is good question about this tricky theme: stackoverflow.com/questions/12552863/….
  • yongtw123
    yongtw123 almost 9 years
    a caveat: when using BufferedWriter write(String string) if one expects a new line after each string written, newLine() should be called
  • Henry Zhu
    Henry Zhu almost 9 years
    Good answer, although its better to use System.getProperty( "line.separator" ) for a new line rather than "\n".
  • RadijatoR
    RadijatoR almost 9 years
    Why is FileWriter treated like expensive writer?
  • Kip
    Kip almost 9 years
    @RadijatoR Because it has to do disk I/O operations. In the JavaDoc for BufferedWriter, it says "In general, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is advisable to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters"
  • Buffalo
    Buffalo almost 9 years
    The problem with this approach is that it opens and closes the output stream every single time. Depending on what and how often you write to your file, this could result in a ridiculous overhead.
  • Rahbee Alvee
    Rahbee Alvee almost 9 years
    This can be done in one line of code. Hope this helps :) Files.write(Paths.get(fileName), msg.getBytes(), StandardOpenOption.APPEND);
  • Evgeni Sergeev
    Evgeni Sergeev over 8 years
    The File and filename-based constructors of PrintWriter mention that they buffer automatically. But when a PrintWriter wraps another Writer, there is no comment in the docs on whether it adds another layer of buffering or not. Given the ambiguity, it seems best to include a BufferedWriter explicitly, as in this answer.
  • Evgeni Sergeev
    Evgeni Sergeev over 8 years
    Hmm, for some reason PrintWriter.close() is not declared as throws IOException in the docs. Looking at its source, the close() method, indeed, cannot throw IOException, because it catches it from the underlying stream, and sets a flag. So if you're working on the code for the next Space Shuttle or an X-ray dose metering system, you should use PrintWriter.checkError() after attempting to out.close(). This should really have been documented.
  • syfantid
    syfantid about 8 years
    @etech Will the second approach need the flush method?
  • Decoded
    Decoded about 8 years
    Thanks Emily L. I've edited the answer to reflect that good catch!
  • Kip
    Kip about 8 years
    @Decoded your suggested edit was a syntax error. out is only defined in the try block. In the finally block it does not exist. You would have to move the declaration of out out of the try block. This is exactly the problem that the Java 7+ syntax resolves. As I've noted, I've left exception handling for the reader; I think it's beyond the scope of this answer.
  • Kip
    Kip about 8 years
    @Decoded I've rolled back your edit on this answer, as it does not compile.
  • Kip
    Kip about 8 years
    If we're going to be super paranoid about closing, each of those XX.close() should be in its own try/catch, right? For example, out.close() could throw an exception, in which case bw.close() and fw.close() would never get called, and fw is the one that is most critical to close.
  • WestCoastProjects
    WestCoastProjects over 7 years
    umm ... what?? This will overwrite the file.
  • Decoded
    Decoded over 7 years
    @Kip, What was the issue? I must have entered a "typo".
  • Kip
    Kip over 7 years
    @Decoded you had fw.close() in a finally block, without a nested try/catch (.close() can throw IOException)
  • php_coder_3809625
    php_coder_3809625 over 7 years
    How bout try-with-resources? try(FileWriter fw = new FileWriter(filename,true)){ // Whatever }catch(IOException ex){ ex.printStackTrace(); }
  • Bhaskara Arani
    Bhaskara Arani over 7 years
    what is obj.toJSONString() here?
  • Gherbi Hicham
    Gherbi Hicham over 7 years
    @BhaskaraArani It's just a string, he put an example of a JSON object converted to a string but the idea is that it could be any string.
  • i000174
    i000174 over 7 years
    You should close only the out variable! stackoverflow.com/questions/484925/…
  • MartyIX
    MartyIX over 7 years
  • David Charles
    David Charles about 7 years
    The above is just a quick example implementation of the solution presented At this link. So you can copy and and run the code and immediately see how it works, be sure that the output.out file is in the same directory as the Writer.java file
  • Konstantin K
    Konstantin K about 7 years
    @Buffalo is right. But you can always use StringBuilder for building large chunks (that are worth writing) before writing them to file.
  • Steve Chambers
    Steve Chambers almost 7 years
    A couple of possible "gotchas" with the Java 7 method: (1) If the file doesn't already exist, StandardOpenOption.APPEND won't create it - kind of like a silent failure as it won't throw an exception either. (2) Using .getBytes() will mean there is no return character before or after the appended text. Have added an alternative answer to address these.
  • Kip
    Kip almost 7 years
    @SteveChambers Thanks for the input. I couldn't believe that append mode does not create the file if it does not exist, so I had to try it to confirm. Not sure what they were thinking there... I found that it does actually throw an exception, but if you copy/paste my code and leave the catch block blank, then you don't see it. I've updated my answer to reflect these issues and I added a link to your answer.
  • Michael
    Michael almost 7 years
    Is it safe to use the faster, buffered operations? I'm trying to log something that happens right before a crash, and I need to make sure the file is going to get written.
  • Kip
    Kip almost 7 years
    @Michael when the buffered writer is closed, it will write whatever is in the buffer. Or you can explicitly call flush() to force it to flush its buffer (writing the contents) immediately.
  • evg345
    evg345 over 6 years
    its may be not enough:) better version is Files.write(Paths.get(fileName), msg.getBytes(), StandardOpenOption.APPEND, StandardOpenOption.CREATE);
  • Andrew Koster
    Andrew Koster over 5 years
    "If you need robust exception handling for older Java, it gets very verbose." If by "verbose" you mean "a horrifying abomination".
  • Enigmatic
    Enigmatic over 5 years
    Do you need to check if the file exists? I thought.CREATE does the job for you.
  • Janac Meena
    Janac Meena about 5 years
    This works in Scala as well: try { Files.write(Paths.get("myfile.txt"), "the text".getBytes(), StandardOpenOption.APPEND) } catch { case ioe: IOException => { println("IOException thrown!") } case e: Exception => println("Non-IOException thrown!") }
  • Rafael Membrives
    Rafael Membrives almost 4 years
    @KonstantinK but then all the content you need to write is loaded into memory.
  • Steve Chambers
    Steve Chambers over 3 years
    If .CREATE is used when the file already exists it silently fails to append anything - no exception is thrown but the existing file contents remain unchanged.
  • lapo
    lapo over 3 years
    Using APPEND + CREATE works perfectly, no check necessary: Files.write(Paths.get("test.log"), (Instant.now().toString() + "\r\n").getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
  • Weekend
    Weekend about 2 years
    The Files.writeString() and Path.of() are both no symbol error, is it a typo?
  • Kip
    Kip about 2 years
    @Weekend it worked when i wrote the answer but i haven't done any serious java development in quite a long time 🤷