[java] Find a line in a file and remove it

So, whenever I hear someone mention that they want to filter out text, I immediately think to go to Streams (mainly because there is a method called filter which filters exactly as you need it to). Another answer mentions using Streams with the Apache commons-io library, but I thought it would be worthwhile to show how this can be done in standard Java 8. Here is the simplest form:

public void removeLine(String lineContent) throws IOException
{
    File file = new File("myFile.txt");
    List<String> out = Files.lines(file.toPath())
                        .filter(line -> !line.contains(lineContent))
                        .collect(Collectors.toList());
    Files.write(file.toPath(), out, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
}

I think there isn't too much to explain there, basically Files.lines gets a Stream<String> of the lines of the file, filter takes out the lines we don't want, then collect puts all of the lines of the new file into a List. We then write the list over top of the existing file with Files.write, using the additional option TRUNCATE so the old contents of the file are replaced.

Of course, this approach has the downside of loading every line into memory as they all get stored into a List before being written back out. If we wanted to simply modify without storing, we would need to use some form of OutputStream to write each new line to a file as it passes through the stream, like this:

public void removeLine(String lineContent) throws IOException
{
    File file = new File("myFile.txt");
    File temp = new File("_temp_");
    PrintWriter out = new PrintWriter(new FileWriter(temp));
    Files.lines(file.toPath())
        .filter(line -> !line.contains(lineContent))
        .forEach(out::println);
    out.flush();
    out.close();
    temp.renameTo(file);
}

Not much has been changed in this example. Basically, instead of using collect to gather the file contents into memory, we use forEach so that each line that makes it through the filter gets sent to the PrintWriter to be written out to the file immediately and not stored. We have to save it to a temporary file, because we can't overwrite the existing file at the same time as we are still reading from it, so then at the end, we rename the temp file to replace the existing file.