foreach-ui logo
codeLanguages
account_treeDSA

Quick Actions

quizlock Random Quiz
trending_uplock Progress
  • 1
  • 2
  • 3
  • 4
  • quiz
Java
  • Understand the concept of streams in Java I/O
  • Learn the difference between byte and character streams
  • Master binary file operations
  • Work with directories and file listings
  • Understand Java NIO (New I/O) basics and Path API

Working with Files and Streams

Beyond basic file reading and writing, Java offers streams for more sophisticated file operations and the NIO API for better performance.

Understanding Streams

In Java, streams are sequences of data. Two main categories:

Byte Streams (for binary data)

  • InputStream and OutputStream
  • Work with raw bytes (8-bit)
  • Used for images, audio, video, executables

Character Streams (for text data)

  • Reader and Writer
  • Work with characters (16-bit Unicode)
  • Handle character encoding automatically
  • Used for text files

Binary File Operations

Reading Binary Files

import java.io.*;

public void copyBinaryFile(String source, String destination) {
    try (FileInputStream in = new FileInputStream(source);
         FileOutputStream out = new FileOutputStream(destination)) {
        
        byte[] buffer = new byte[1024];
        int bytesRead;
        
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        
        System.out.println("File copied successfully!");
    } catch (IOException e) {
        System.out.println("Error: " + e.getMessage());
    }
}

Working with Data Streams

// Writing primitive types to binary file
try (DataOutputStream out = new DataOutputStream(
        new FileOutputStream("data.bin"))) {
    out.writeInt(42);
    out.writeDouble(3.14);
    out.writeUTF("Hello, World!");
} catch (IOException e) {
    e.printStackTrace();
}

// Reading primitive types from binary file
try (DataInputStream in = new DataInputStream(
        new FileInputStream("data.bin"))) {
    int number = in.readInt();
    double pi = in.readDouble();
    String text = in.readUTF();
    System.out.println(number + ", " + pi + ", " + text);
} catch (IOException e) {
    e.printStackTrace();
}

Working with Directories

Listing Directory Contents

File dir = new File("myFolder");
File[] files = dir.listFiles();

if (files != null) {
    for (File file : files) {
        if (file.isDirectory()) {
            System.out.println("[DIR] " + file.getName());
        } else {
            System.out.println("[FILE] " + file.getName() + 
                " (" + file.length() + " bytes)");
        }
    }
}

Creating Directory Trees

File dir = new File("parent/child/grandchild");
if (dir.mkdirs()) {
    System.out.println("Directory tree created");
}

Java NIO (New I/O)

Java 7 introduced the NIO.2 API with the Path and Files classes, providing more powerful file operations.

Path API

import java.nio.file.*;

// Creating paths
Path path1 = Paths.get("data.txt");
Path path2 = Paths.get("/home/user/documents");
Path path3 = path2.resolve("file.txt");  // Combine paths

// Path information
System.out.println("File name: " + path1.getFileName());
System.out.println("Parent: " + path1.getParent());
System.out.println("Absolute: " + path1.toAbsolutePath());

Files Utility Class

import java.nio.file.*;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;

// Reading all lines at once
try {
    List<String> lines = Files.readAllLines(Paths.get("data.txt"));
    for (String line : lines) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

// Writing all lines at once
List<String> lines = Arrays.asList("Line 1", "Line 2", "Line 3");
try {
    Files.write(Paths.get("output.txt"), lines);
} catch (IOException e) {
    e.printStackTrace();
}

Advanced File Operations with NIO

// Copy file
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

// Move file
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);

// Delete file
Files.delete(path);

// Check existence
if (Files.exists(path)) {
    System.out.println("File exists");
}

// Get file attributes
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("Size: " + attrs.size());
System.out.println("Created: " + attrs.creationTime());
System.out.println("Modified: " + attrs.lastModifiedTime());

Walking Directory Trees

import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.io.IOException;

// List all files recursively
try (Stream<Path> paths = Files.walk(Paths.get("myFolder"))) {
    paths.filter(Files::isRegularFile)
         .forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}

// Custom directory visitor
Files.walkFileTree(Paths.get("myFolder"), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("File: " + file);
        return FileVisitResult.CONTINUE;
    }
    
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("Directory: " + dir);
        return FileVisitResult.CONTINUE;
    }
});

Real-World Example: Log File Analyzer

import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;

public class LogAnalyzer {
    public void analyzeLogFile(String logFile) {
        try (Stream<String> lines = Files.lines(Paths.get(logFile))) {
            long errorCount = lines.filter(line -> line.contains("ERROR"))
                                  .count();
            System.out.println("Total errors: " + errorCount);
        } catch (IOException e) {
            System.out.println("Error reading log: " + e.getMessage());
        }
    }
    
    public void findLargeFiles(String directory, long minSize) {
        try (Stream<Path> paths = Files.walk(Paths.get(directory))) {
            paths.filter(Files::isRegularFile)
                 .filter(p -> {
                     try {
                         return Files.size(p) > minSize;
                     } catch (IOException e) {
                         return false;
                     }
                 })
                 .forEach(p -> {
                     try {
                         System.out.println(p + " (" + Files.size(p) + " bytes)");
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Performance Tips

  1. Use buffered streams for better performance
  2. Prefer NIO for bulk operations (copy, move, delete)
  3. Use try-with-resources to prevent resource leaks
  4. Process large files line by line instead of loading all at once
  5. Use appropriate stream types (byte vs character)

Key Takeaways

  • Byte streams for binary data, character streams for text
  • InputStream/OutputStream hierarchy for byte operations
  • Reader/Writer hierarchy for character operations
  • Java NIO provides modern, powerful file operations
  • Path and Files classes simplify common file tasks
  • Stream API integration makes file processing elegant
  • Always handle IOException appropriately

Congratulations!

You've completed the Exception Handling and File I/O chapter! You now know:

  • How to handle exceptions gracefully
  • How to read and write text files
  • How to work with binary files
  • How to use Java NIO for advanced operations
  • Best practices for file I/O

These skills are essential for real-world Java development!

© 2026 forEach. All rights reserved.

Privacy Policy•Terms of Service