Find a line in a file and remove it

后端 未结 16 1860
谎友^
谎友^ 2020-11-22 13:06

I\'m looking for a small code snippet that will find a line in file and remove that line (not content but line) but could not find. So for example I have in a file following

16条回答
  •  不知归路
    2020-11-22 13:52

    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 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 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.

提交回复
热议问题