Lesson Completion
Back to course

NIO.2: Modern Path and Files APIs

Beginner
12 minutes4.5Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: NIO.2 (Java 7+, java.nio.file) provides modern file I/O. Path = file/directory reference (replaces File). Files class = static utility methods for all operations.
  • Key methods: Files.readAllLines() (read entire file), Files.write() (write), Files.copy()/move()/delete() (operations), Files.walk() (recursive traversal), Files.lines() (lazy Stream). Always use UTF-8 explicitly! Supports symbolic links, file attributes, watch services. Preferred over File class!

Think of GPS navigation. Old File class = paper map (clunky, manual). NIO.2 Path/Files = GPS (modern, automatic, feature-rich). Both get you there, but GPS is WAY better!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Path: Address in GPS (just location, not the actual place)
  • Files: GPS operations (navigate, measure distance, find shortcuts)
  • Files.walk(): Exploring entire neighborhood street-by-street

3. Technical Mastery (The "Deep Dive")

Common Files Operations

CategoryMethodPurpose
ReadingreadAllBytes(), readAllLines(), lines()Read files
Writingwrite(), writeString()Write files
Operationscopy(), move(), delete()Manipulate files
Checksexists(), isDirectory(), isReadable()File info
Directorylist(), walk(), walkFileTree()Traverse
CreationcreateFile(), createDirectory()Create

4. Interactive & Applied Code

java
import java.nio.file.*; import java.nio.charset.StandardCharsets; import java.io.IOException; import java.util.*; import java.util.stream.*; public class NIO2Demo { public static void main(String[] args) throws Exception { demonstratePathOperations(); demonstrateFileReading(); demonstrateFileWriting(); demonstrateFileOperations(); demonstrateDirectoryOperations(); } // Path operations static void demonstratePathOperations() { System.out.println("=== PATH OPERATIONS ==="); Path path = Paths.get("folder", "subfolder", "file.txt"); System.out.println("Path: " + path); System.out.println("File name: " + path.getFileName()); System.out.println("Parent: " + path.getParent()); System.out.println("Root: " + path.getRoot()); System.out.println("Absolute: " + path.toAbsolutePath()); // Path manipulation Path path2 = Paths.get("other.txt"); Path relative = path.relativize(path2); System.out.println("Relative path: " + relative); } // Reading files (multiple ways) static void demonstrateFileReading() throws Exception { System.out.println("\n=== FILE READING ==="); Path file = Paths.get("sample.txt"); // Create sample file Files.writeString(file, "Line 1\nLine 2\nLine 3\n", StandardCharsets.UTF_8); // Method 1: Read all lines into List List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8); System.out.println("Read all lines: " + lines); // Method 2: Read all bytes byte[] bytes = Files.readAllBytes(file); System.out.println("Read bytes: " + new String(bytes)); // Method 3: Stream lines (lazy, memory-efficient) try (Stream<String> stream = Files.lines(file, StandardCharsets.UTF_8)) { long count = stream.filter(line -> line.startsWith("Line")).count(); System.out.println("Lines starting with 'Line': " + count); } // Method 4: BufferedReader try (var reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { String line; while ((line = reader.readLine()) != null) { System.out.println(" " + line); } } } // Writing files static void demonstrateFileWriting() throws Exception { System.out.println("\n=== FILE WRITING ==="); Path file = Paths.get("output.txt"); // Method 1: Write string (Java 11+) Files.writeString(file, "Hello, NIO.2!\n", StandardCharsets.UTF_8); // Method 2: Write lines List<String> lines = Arrays.asList("Line 1", "Line 2", "Line 3"); Files.write(file, lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND); // Append mode // Method 3: BufferedWriter try (var writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8, StandardOpenOption.APPEND)) { writer.write("Line 4\n"); } System.out.println("File written: " + file); } // File operations static void demonstrateFileOperations() throws Exception { System.out.println("\n=== FILE OPERATIONS ==="); Path source = Paths.get("source.txt"); Path dest = Paths.get("dest.txt"); Path moved = Paths.get("moved.txt"); // Create source Files.writeString(source, "Source content"); // Copy Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); System.out.println("Copied: " + source + " -> " + dest); // Move Files.move(dest, moved, StandardCopyOption.REPLACE_EXISTING); System.out.println("Moved: " + dest + " -> " + moved); // Delete Files.deleteIfExists(moved); System.out.println("Deleted: " + moved); // File info if (Files.exists(source)) { System.out.println("Size: " + Files.size(source) + " bytes"); System.out.println("Last modified: " + Files.getLastModifiedTime(source)); System.out.println("Is readable: " + Files.isReadable(source)); } } // Directory operations static void demonstrateDirectoryOperations() throws Exception { System.out.println("\n=== DIRECTORY OPERATIONS ==="); // Create directory Path dir = Paths.get("testdir"); Files.createDirectories(dir); // Creates parent dirs if needed // Create files in directory Files.writeString(dir.resolve("file1.txt"), "File 1"); Files.writeString(dir.resolve("file2.txt"), "File 2"); Files.createDirectory(dir.resolve("subdir")); // List directory (non-recursive) System.out.println("Directory contents:"); try (Stream<Path> stream = Files.list(dir)) { stream.forEach(path -> System.out.println(" " + path.getFileName())); } // Walk directory tree (recursive) System.out.println("\nRecursive walk:"); try (Stream<Path> stream = Files.walk(dir)) { stream.forEach(path -> System.out.println(" " + path)); } // Find files (with filter) System.out.println("\nFind .txt files:"); try (Stream<Path> stream = Files.find(dir, 10, (path, attrs) -> path.toString().endsWith(".txt"))) { stream.forEach(path -> System.out.println(" " + path.getFileName())); } } }

5. The Comparison & Decision Layer

TaskOld (File)New (NIO.2)
Read fileFileReader + BufferedReaderFiles.readAllLines()
Write fileFileWriter + BufferedWriterFiles.writeString()
Copy fileManual byte copyFiles.copy()
List directoryfile.listFiles()Files.list() (Stream)
Recursive walkManual recursionFiles.walk()

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "What's the difference between Files.list() and Files.walk()?" Answer:

  • Files.list(): Shallow (one level only, direct children)
  • Files.walk(): Deep (recursive, entire subtree)
java
// Directory structure: // dir/ // file1.txt // subdir/ // file2.txt // list() returns: file1.txt, subdir (2 items) Files.list(Paths.get("dir")).forEach(System.out::println); // walk() returns: dir, file1.txt, subdir, file2.txt (4 items) Files.walk(Paths.get("dir")).forEach(System.out::println);

Pro-Tip: Always close Streams from Files methods:

java
// ❌ RESOURCE LEAK Files.list(dir).forEach(System.out::println); // Stream not closed → file handles leak! // ✅ CORRECT try (Stream<Path> stream = Files.list(dir)) { stream.forEach(System.out::println); } // Auto-closed

Files.list(), Files.walk(), Files.lines() return AutoCloseable streams!

Topics Covered

Java Fundamentals

Tags

#java#programming#beginner-friendly

Last Updated

2025-02-01