Lesson 33 • Advanced

    IO & NIO

    Every real application reads and writes data. Java offers two approaches: the classic IO library (stream-based, simple) and the modern NIO.2 API (buffer-based, powerful). Knowing when to use each is the mark of a skilled developer.

    Before You Start

    You should know Exception Handling (try-with-resources) and Streams API (since NIO.2 returns Stream<Path>). Basic understanding of byte vs character data helps.

    What You'll Learn

    • ✅ InputStream/OutputStream vs Reader/Writer
    • ✅ BufferedReader and try-with-resources
    • ✅ NIO.2: Path, Files, and FileChannel
    • ✅ Watching directories with WatchService
    • ✅ Memory-mapped files for performance
    • ✅ Choosing between IO and NIO

    1️⃣ IO vs NIO — When to Use Which

    Analogy: Classic IO is like drinking through a straw — data flows one direction, one byte at a time. NIO is like a bucket brigade — you fill buffers, pass them through channels, and can even read and write simultaneously.

    FeatureIO (java.io)NIO (java.nio)
    ModelStream-based (byte by byte)Buffer + Channel (block-based)
    BlockingAlways blockingNon-blocking possible (Selectors)
    DirectionOne-way (in or out)Bidirectional channels
    Best forSimple reads/writesHigh-performance, large files

    Try It: Classic IO File Operations

    Try it Yourself »
    JavaScript
    // 💡 Try modifying this code and see what happens!
    // Simulating Java Classic IO operations
    
    console.log("=== Classic IO File Operations ===\n");
    
    // Simulate a file system in memory
    const fileSystem = new Map();
    
    // Writing to a file (FileWriter + BufferedWriter)
    function writeFile(path, content) {
      fileSystem.set(path, content);
      return content.length;
    }
    
    // Reading a file (FileReader + BufferedReader)
    function readFile(path) {
      if (!fileSystem.has(path)) throw new Error("FileNotFoundExcep
    ...

    2️⃣ NIO.2 — The Modern Approach

    For most file operations, the NIO.2 Files utility class (Java 7+) is the best starting point. It wraps complex channel operations into simple one-liners. Use Path instead of the legacy File class everywhere.

    Files.readString(path) — Java 11+, read entire small file

    Files.lines(path) — lazy Stream for large files

    Files.walk(dir) — recursive directory traversal

    Files.copy(src, dst) — efficient file copying

    Try It: NIO.2 Path & Files API

    Try it Yourself »
    JavaScript
    // 💡 Try modifying this code and see what happens!
    // Simulating Java NIO.2 Path and Files operations
    
    console.log("=== NIO.2 Path & Files API ===\n");
    
    // Simulated file system with Path-like API
    const fs = new Map();
    fs.set("/project/src/Main.java", "public class Main {}");
    fs.set("/project/src/Utils.java", "public class Utils {}");
    fs.set("/project/src/test/TestMain.java", "class TestMain {}");
    fs.set("/project/README.md", "# My Project");
    fs.set("/project/pom.xml", "<project>...</project>")
    ...

    Common Mistakes

    • ⚠️ Not closing resources: Always use try-with-resources. Unclosed streams leak file handles and can crash your OS
    • ⚠️ Reading entire large files into memory: Use Files.lines() (returns lazy Stream) instead of readAllLines() for GB-sized files
    • ⚠️ Using java.io.File in new code: It's legacy. Use Path and Files from java.nio.file
    • ⚠️ Forgetting character encoding: Always specify StandardCharsets.UTF_8 — the default varies by OS!

    Pro Tips

    • 💡 Files.readString(path) (Java 11+) — one-liner to read an entire small file
    • 💡 Files.walk(dir) returns a Stream<Path> — combine with filter/map for elegant directory traversal
    • 💡 Memory-mapped files (FileChannel.map()) give you the fastest I/O for large files — the OS handles caching
    • 💡 WatchService lets you monitor directories for changes — essential for hot-reload features

    Try It: FileChannel & WatchService

    Try it Yourself »
    JavaScript
    // 💡 Try modifying this code and see what happens!
    // Simulating FileChannel operations and WatchService
    
    console.log("=== FileChannel & WatchService ===\n");
    
    // 1. FileChannel — buffer-based I/O
    console.log("1. FILECHANNEL (buffer-based):");
    let buffer = new ArrayBuffer(1024);
    let view = new Uint8Array(buffer);
    let message = "Hello, NIO!";
    for (let i = 0; i < message.length; i++) view[i] = message.charCodeAt(i);
    console.log("  Allocated ByteBuffer(1024)");
    console.log("  Written: \"" + messag
    ...

    📋 Quick Reference

    TaskAPINotes
    Read fileFiles.readString(path)Java 11+, small files
    Write fileFiles.writeString(path, s)Creates or overwrites
    Stream linesFiles.lines(path)Lazy, memory-efficient
    Walk treeFiles.walk(dir)Returns Stream<Path>
    Fast copyFileChannel.transferTo()Zero-copy for large files

    🎉 Lesson Complete!

    You've mastered Java IO & NIO — from simple file reads to high-performance channels! Next: JDBC — connecting Java to databases.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service