Lab 11: File I/O — NIO.2
Objective
Read and write files using modern Java NIO.2 (java.nio.file), work with Paths, copy/move/delete files, walk directory trees, and process large files with streams.
Background
Java's NIO.2 API (java.nio.file.Files, Path, Paths) replaced the old java.io.File class in Java 7. It's more expressive, throws meaningful exceptions, supports symbolic links, and integrates cleanly with streams. Every Java backend developer works with the filesystem daily — config files, logs, uploads, reports.
Time
40 minutes
Prerequisites
Lab 09 (Collections)
Lab 10 (Exception Handling)
Tools
Java 21 (Eclipse Temurin)
Docker image:
innozverse-java:latest
Lab Instructions
Step 1: Path Basics
💡
Path.of()replacedPaths.get()in Java 11. Paths are immutable value objects — operations likeresolve()andnormalize()return new Path instances. Think of Path as a "smart string" for file locations, not a reference to a physical file.
📸 Verified Output:
Step 2: Reading Files
💡
Files.readString()/readAllLines()are convenient for small files. For large files (logs, CSVs with millions of rows), useFiles.lines()— it returns a lazyStream<String>that reads one line at a time. Always use it in try-with-resources to close the underlying file handle.
📸 Verified Output:
Step 3: Writing Files
💡
StandardOpenOptioncontrols write behavior:WRITE(default),APPEND,CREATE,CREATE_NEW,TRUNCATE_EXISTING.CREATE_NEWthrows if the file already exists — useful for preventing accidental overwrites.BufferedWriterbatches small writes into larger OS calls, dramatically improving performance.
📸 Verified Output:
Step 4: File Operations — Copy, Move, Delete
💡
REPLACE_EXISTINGis the key option forcopy()andmove()— without it they throw if the destination exists.Files.createDirectories()creates the full path including parents (likemkdir -p). PreferdeleteIfExists()overdelete()to avoidNoSuchFileException.
📸 Verified Output:
Step 5: Walking Directory Trees
💡
Files.walk()vsFiles.find():walk()returns all paths at all depths;find()takes aBiPredicate<Path, BasicFileAttributes>for filtering — more efficient since attributes are read once. Both return lazy streams — use try-with-resources or they may leak file handles on some platforms.
📸 Verified Output:
Step 6: Watching a Directory
💡
WatchServiceuses OS-level file system notifications (inotify on Linux, FSEvents on macOS, ReadDirectoryChangesW on Windows) — it doesn't poll. This makes it efficient for build tools, config reloaders, and hot-reload systems.key.reset()is mandatory to receive future events.
📸 Verified Output:
Step 7: Working with Temp Files & System Properties
💡
Files.createTempFile(prefix, suffix)creates a file in the system temp directory with a guaranteed unique name. Use it for intermediate processing, test fixtures, or downloads.deleteOnExit()registers a JVM shutdown hook — but for long-running servers, explicitly delete temp files to avoid filling up/tmp.
📸 Verified Output:
Step 8: Complete Example — CSV Log Analyzer
💡
UncheckedIOExceptionwrapsIOExceptionin aRuntimeExceptionso it can be thrown inside lambdas (which can't declare checked exceptions). This is the standard Java pattern for using checked exceptions in streams. Alternatively, extract the lambda to a named method withthrows.
📸 Verified Output:
Verification
Summary
You've covered Path operations, Files.readString/writeString, Files.lines() for streaming large files, copy/move/delete, directory walking with Files.walk(), WatchService for filesystem events, temp files, and the CSV log analyzer. NIO.2 is the modern standard for all Java file work.
Further Reading
Last updated
