Reading Files
Read text and binary files using the modern java.nio.file.Files API and classic BufferedReader.
Overview
Key Points
- •Path.of("filename.txt") or Paths.get("filename.txt") creates a Path
- •Files.readString(path) reads the entire file as a String (Java 11+)
- •Files.readAllLines(path) reads all lines into a List<String>
- •Files.lines(path) returns a Stream<String> for lazy line-by-line reading
- •BufferedReader wraps a FileReader for efficient character reading
- •BufferedReader.readLine() returns null at end-of-file
- •Always use try-with-resources: readers and streams must be closed
- •Specify charset explicitly: StandardCharsets.UTF_8
Examples
Reading a file with Files (modern NIO)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
// Create a temp file for demonstration
Path path = Files.createTempFile("demo", ".txt");
Files.writeString(path, "line one\nline two\nline three");
// Read all lines as a list
List<String> lines = Files.readAllLines(path);
System.out.println("Lines: " + lines.size());
for (String line : lines) {
System.out.println("> " + line);
}
// Read entire file as one String
String content = Files.readString(path);
System.out.println("Content length: " + content.length());
// Lazy stream for large files
System.out.println("Words per line:");
try (var stream = Files.lines(path)) {
stream.forEach(line -> System.out.println(line + " -> " + line.split("\\s+").length + " word(s)"));
}
Files.delete(path); // cleanup
}
}Files.lines() returns a Stream that holds a reader. Always close it with try-with-resources. Files.readAllLines() closes the file automatically after reading.
Reading with BufferedReader (classic API)
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
Path path = Files.createTempFile("demo", ".txt");
Files.writeString(path, "alpha\nbeta\ngamma");
// BufferedReader with try-with-resources
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(path.toFile()), StandardCharsets.UTF_8))) {
String line;
int lineNum = 1;
while ((line = reader.readLine()) != null) {
System.out.printf("%d: %s%n", lineNum++, line);
}
}
// Simpler: Files.newBufferedReader
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
reader.lines().forEach(System.out::println);
}
Files.delete(path);
}
}readLine() returns null at end of file, not an exception. The while ((line = reader.readLine()) != null) idiom is the standard loop pattern for BufferedReader.
Processing a CSV-like file with streams
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) throws IOException {
Path path = Files.createTempFile("data", ".csv");
Files.writeString(path, "Alice,30,Engineer\nBob,25,Designer\nCarol,35,Manager\nDave,28,Engineer");
// Parse and filter: find all Engineers
try (var lines = Files.lines(path)) {
Map<String, List<String[]>> byRole = lines
.map(l -> l.split(","))
.filter(parts -> parts.length == 3)
.collect(Collectors.groupingBy(parts -> parts[2]));
byRole.forEach((role, people) -> {
System.out.println(role + ":");
people.forEach(p -> System.out.println(" " + p[0] + " (age " + p[1] + ")"));
});
}
Files.delete(path);
}
}Files.lines() combined with stream operations is a concise way to process large files line by line without loading the entire file into memory.
Common Mistakes
- Not closing Files.lines() stream. It holds an open file handle. Always wrap in try-with-resources
- Using FileReader directly without BufferedReader. FileReader reads character by character which is very slow. Wrap it in BufferedReader
- Hardcoding the platform default charset. Always specify StandardCharsets.UTF_8 or Charset.forName("UTF-8") explicitly to avoid encoding bugs on different platforms
Note
For small to medium files, Files.readAllLines() or Files.readString() is the simplest approach. For large files (hundreds of MB), use Files.lines() with a stream pipeline to avoid loading everything into memory.
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4