Reading — step 1 of 6
Learn
Java's modern file I/O lives in java.nio.file. The classic java.io.File works but is more verbose and less ergonomic. Use NIO for new code.
Reading a small file
import java.nio.file.*;
String contents = Files.readString(Path.of("data.txt"));
// Or:
List<String> lines = Files.readAllLines(Path.of("data.txt"));
Files.readString (Java 11+) reads the entire file as one string. readAllLines returns each line in a list. Both load the whole file into memory — fine for small files, dangerous for huge ones.
Writing
Files.writeString(Path.of("output.txt"), "Hello, file!\n");
Files.write(Path.of("log.txt"), List.of("line 1", "line 2", "line 3"));
// Append instead of overwrite:
Files.writeString(
Path.of("log.txt"),
"new line\n",
StandardOpenOption.APPEND, StandardOpenOption.CREATE
);
Streaming a large file line by line
try (Stream<String> lines = Files.lines(Path.of("huge.log"))) {
long errors = lines
.filter(line -> line.contains("ERROR"))
.count();
System.out.println("errors: " + errors);
}
Files.lines returns a Stream — values come one at a time, constant memory regardless of file size. Always wrap in try-with-resources so the underlying file handle gets closed.
Try-with-resources — the cleanup pattern
Anything that implements AutoCloseable can be auto-closed:
try (BufferedReader br = Files.newBufferedReader(Path.of("data.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} // br automatically closed here, even on exception
Cleaner than the old try/finally { f.close() } pattern. Multiple resources separated by ; close in reverse declaration order.
Path basics
Path p = Path.of("data", "users", "alice.json");
p.toString(); // "data/users/alice.json" (or backslashes on Windows)
p.getFileName(); // "alice.json"
p.getParent(); // "data/users"
p.getNameCount(); // 3
p.resolve("backup.json"); // "data/users/backup.json" — joins paths
Path.of is the modern way; Paths.get is the older equivalent. Both work.
Common file operations
Files.exists(p);
Files.isDirectory(p);
Files.size(p); // bytes
Files.delete(p); // throws if missing
Files.deleteIfExists(p); // doesn't throw
Files.copy(src, dst, REPLACE_EXISTING);
Files.move(src, dst, REPLACE_EXISTING);
Files.createDirectories(p); // mkdir -p
Files.list(p); // direct children as Stream
Files.walk(p); // recursive Stream
Common mistakes
- Forgetting try-with-resources with
Files.lines— the file handle leaks until GC. - Using
Files.readAllLineson a 5GB file — OOM. UseFiles.lineswith a stream. - Hardcoding
/in paths — works on *nix but breaks on Windows. UsePath.of("a", "b")to construct. - Catching
Exceptionto swallow IOException — handle specifically; log or surface.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…