To use Files.lines() to process a text file line by line in Java, you should follow the pattern of returning a Stream<String> within a try-with-resources block. This approach is memory-efficient because it reads the file lazily, meaning it doesn’t load the entire file into memory at once.
Basic Implementation
package org.kodejava.nio;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class FileStreamExample {
public static void main(String[] args) {
Path path = Paths.get("example.txt");
// Use try-with-resources to ensure the stream (and underlying file) is closed
try (Stream<String> lines = Files.lines(path)) {
lines.forEach(System.out::println);
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}
}
}
Advanced Processing (Filtering and Mapping)
The power of Files.lines() comes from the Stream API, allowing you to filter, transform, or search through the file content easily:
try (Stream<String> lines = Files.lines(path)) {
long count = lines
.filter(line -> line.contains("ERROR")) // Only keep lines with "ERROR"
.map(String::trim) // Remove whitespace
.peek(System.out::println) // Print each matching line
.count(); // Count the occurrences
System.out.println("Total errors found: " + count);
} catch (IOException e) {
e.printStackTrace();
}
Key Considerations:
- Try-with-Resources is Mandatory: Unlike most streams, the stream returned by
Files.lines()holds an open resource (the file handle). If you don’t close it, you may run into a “too many open files” error. - Character Encoding: By default,
Files.lines()uses UTF-8. If your file uses a different encoding (like ISO-8859-1), you can specify it as a second argument:Files.lines(path, StandardCharsets.ISO_8859_1) -
Performance: For very large files,
Files.lines()is significantly more efficient thanFiles.readAllLines(), which would attempt to store every line in aList<String>, potentially causing anOutOfMemoryError.
