Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to read a file line by line

Short answer

Suppose there is a file log.txt:

INFO start
ERROR disk full
INFO retry
ERROR timeout

Files.lines() reads the file lazily, one line at a time. The stream keeps the file open, so wrap it in a try-with-resources — it closes the file for you:

void main() throws IOException {
    try (Stream<String> lines = Files.lines(Path.of("log.txt"))) {
        lines.filter(line -> line.startsWith("ERROR")).forEach(IO::println);
    }
}

Output:

ERROR disk full
ERROR timeout

BufferedReader

The classic way is to read in a loop until readLine() returns null:

void main() throws IOException {
    try (BufferedReader reader = Files.newBufferedReader(Path.of("log.txt"))) {
        String line;
        while ((line = reader.readLine()) != null) {
            IO.println(line.length() + " " + line);
        }
    }
}

Output:

10 INFO start
15 ERROR disk full
10 INFO retry
13 ERROR timeout

With line numbers

Keep a counter in the loop:

void main() throws IOException {
    try (var reader = Files.newBufferedReader(Path.of("log.txt"))) {
        int number = 0;
        String line;
        while ((line = reader.readLine()) != null) {
            number++;
            if (line.contains("timeout")) {
                IO.println("line " + number + ": " + line);
            }
        }
    }
}

Output:

line 4: ERROR timeout

Common mistake

Using Files.lines() without try. The file stays open until garbage collection; in a long-running program open files pile up and the system stops opening new ones. Always write try (var lines = Files.lines(...)).

Functions used in this recipe

  • Files.lines() — Reads a file lazily as a stream of lines, without loading it into memory.
  • BufferedReader — Reads text line by line with buffering — the classic way to process large files.
  • Files.readAllLines() — Reads a text file into a list of lines.

Thanks for reading!

Donate to the site — we work hard for you.