java.io, part of Java since 1.0, provides stream-based classes (InputStream, Reader, BufferedReader) for reading and writing bytes or characters sequentially. java.nio.file, added in Java 7, introduced Path (a more capable, filesystem-aware replacement for the old File class) and the Files utility class, whose static convenience methods handle common whole-file operations — reading, writing, copying, walking a directory tree — in a single call each, without manually managing streams for the simple cases.
Files: one-line whole-file operations
For the common case (a whole small-to-medium file), Files' static methods replace what used to require several lines of manual stream setup and try-with-resources.
import java.nio.file.*;
String content = Files.readString(Path.of("data.txt")); // one line, whole file
Files.writeString(Path.of("output.txt"), "hello\n");
List<String> lines = Files.readAllLines(Path.of("data.txt"));
for (Path entry : Files.list(Path.of("."))
.filter(Files::isRegularFile)
.toList()) {
System.out.println(entry.getFileName());
}try-with-resources: automatic, guaranteed cleanup
Any resource implementing AutoCloseable, declared inside the try's parentheses, is automatically closed when the block exits — normally or via an exception — without needing an explicit finally block.
try (BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} // reader.close() is called automatically here, even if an exception was thrown aboveWhen to still use java.io directly
For streaming very large files line-by-line, working with network sockets, or interoperating with older APIs that still expect InputStream/OutputStream, the original java.io classes (or a hybrid, since java.nio.file's Files.newBufferedReader bridges the two) remain the right tool — java.nio.file didn't replace java.io, it added a more convenient layer for the common filesystem cases.