File Handling
File vs NIO.2 (Path, Files), reading and writing text and binary, and walking directories.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
Programs need to remember things beyond a single run - and that means reading and
writing files. Modern Java makes this clean and safe with the NIO.2 API
(Path and Files).
Path: pointing at a file
A Path represents a location in the file system - it doesn't open anything,
it just names a place:
import java.nio.file.Path;
Path file = Path.of("notes", "todo.txt"); // notes/todo.txt
System.out.println(file.getFileName()); // todo.txt
System.out.println(file.getParent()); // notes
System.out.println(file.toAbsolutePath()); // full pathA Path is an address written on paper - it tells you where a house is without
you visiting it. The Files class is the courier who actually goes there to read
the mailbox or drop off a letter. Naming a place and acting on it are separate
steps.
Reading and writing text
For everyday text files, Files has beautifully simple methods:
import java.nio.file.Files;
// Write (creates or overwrites)
Files.writeString(Path.of("todo.txt"), "Learn Java\nBuild a project\n");
// Read the whole file as one String
String content = Files.readString(Path.of("todo.txt"));
// Read as a list of lines
List<String> lines = Files.readAllLines(Path.of("todo.txt"));
for (String line : lines) {
System.out.println(line);
}readString loads the whole file into memory
Files.readString and readAllLines are perfect for small-to-medium files. For
huge files (gigabytes), stream them line by line instead (below) so you don't run
out of memory.
Streaming large files
For big files, process one line at a time with a stream - inside try-with- resources so the file closes automatically:
try (var lines = Files.lines(Path.of("huge.log"))) {
long errors = lines.filter(l -> l.contains("ERROR")).count();
System.out.println("Errors: " + errors);
}Appending, checking, deleting
Files.writeString(Path.of("log.txt"), "New entry\n",
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
boolean exists = Files.exists(Path.of("log.txt"));
long size = Files.size(Path.of("log.txt"));
Files.deleteIfExists(Path.of("temp.txt"));Working with directories
Files.createDirectories(Path.of("data", "reports")); // makes nested dirs
// List files in a directory (try-with-resources closes the stream)
try (var entries = Files.list(Path.of("data"))) {
entries.forEach(System.out::println);
}
// Walk an entire tree recursively
try (var all = Files.walk(Path.of("data"))) {
all.filter(Files::isRegularFile).forEach(System.out::println);
}NIO.2 vs. the old File class
You may see the older java.io.File in tutorials. The newer java.nio.file
API (Path, Files) is more capable, has clearer error handling, and integrates
with streams. Prefer Path/Files in new code.
Binary files
For non-text data (images, serialized objects), read and write raw bytes:
byte[] data = Files.readAllBytes(Path.of("photo.jpg"));
Files.write(Path.of("copy.jpg"), data);Quick check
You need to count matching lines in a 5 GB log file. What's the safest approach?
Key takeaways
- A Path names a file-system location; the Files class performs the actual operations.
- Files.writeString / readString / readAllLines handle small text files simply.
- For large files, stream with Files.lines() inside try-with-resources.
- Files also handles appending, existence checks, sizes, deletion, and directory creation/listing/walking.
- Prefer the modern NIO.2 API (Path, Files) over the older java.io.File.
Next, we'll handle two more everyday essentials: dates & times and the wider world of input/output streams.