Skip to content
Java file handling 4 min read

File Handling

Files are how your programs talk to the outside world between runs. Java gives you a rich, layered set of APIs — from the battle-tested java.io.File class introduced in Java 1.0, all the way to the sleek java.nio.file package that arrived in Java 7 — so you can read configs, write logs, parse CSVs, compress archives, and much more.

Why File Handling Matters

Almost every real application touches the file system at some point: loading settings, persisting data, importing/exporting reports, or reading user-supplied content. Understanding which Java API to reach for — and why — saves you from subtle bugs and poor performance.

A Quick Tour of Java’s File APIs

Java has evolved its file handling story significantly over the decades. Here is a high-level map:

APIPackageIntroducedBest For
Filejava.ioJava 1.0Legacy code; simple existence/metadata checks
Stream classes (FileInputStream, FileReader, …)java.ioJava 1.0Byte-by-byte or character-by-character I/O
RandomAccessFilejava.ioJava 1.0Seek to arbitrary positions; binary records
NIO.2 (Path, Files)java.nio.fileJava 7Modern, concise, exception-rich file operations
ZipInputStream / ZipOutputStreamjava.util.zipJava 1.1Reading and writing .zip archives

Tip: For new code, prefer the java.nio.file (Path / Files) API over the older java.io.File. It throws descriptive exceptions, supports symbolic links, and has atomic operations.

A Minimal Working Example

Before diving into the individual topics, here is a taste of how straightforward file handling can be with modern Java:

import java.nio.file.*;

public class QuickDemo {
    public static void main(String[] args) throws Exception {
        Path file = Path.of("greeting.txt");

        // Write text to a file (creates or overwrites)
        Files.writeString(file, "Hello, file system!");

        // Read it back in one call
        String content = Files.readString(file);
        System.out.println(content);

        // Delete when done
        Files.delete(file);
    }
}

Output:

Hello, file system!

Three lines to write, read, and delete a file — that is the power of java.nio.file.

How It Works Under the Hood

When you call any file API, Java ultimately delegates to the operating system through the JVM’s native layer (JNI). On Linux this means open(2), read(2), write(2), and close(2) system calls; on Windows it maps to CreateFile, ReadFile, etc. The JVM’s FileSystem abstraction hides those differences behind a uniform interface.

Buffering matters. Reading or writing one byte at a time causes one system call per byte — catastrophically slow for large files. Wrapping streams in BufferedInputStream / BufferedOutputStream (or using Files.readAllBytes / Files.writeString) batches I/O into chunks (typically 8 KB), cutting system-call overhead dramatically.

Character encoding. Files store bytes; String holds Unicode characters. Every time you read or write text you are implicitly applying a charset (e.g., UTF-8). If you omit the charset argument in older APIs, Java uses the platform default, which varies by OS — a classic source of encoding bugs. Always specify StandardCharsets.UTF_8 (or pass it to Files methods that accept a Charset).

File handles are OS resources. Forgetting to close a FileInputStream leaks a file descriptor. Always use try-with-resources:

try (var reader = new java.io.FileReader("data.txt")) {
    // use reader
} // automatically closed here

Warning: On Windows, an unclosed file handle prevents other processes from deleting or renaming the file. On Linux the file can be deleted, but the descriptor keeps the data alive until GC — wasting disk space.

Checked vs Unchecked Exceptions

Most java.io methods throw IOException (checked), so the compiler forces you to handle it. java.nio.file methods throw subclasses like NoSuchFileException or FileAlreadyExistsException, giving you much more precise error messages. See Exception Handling for a refresher on checked exceptions.

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

public class SafeRead {
    public static void main(String[] args) {
        try {
            String text = Files.readString(Path.of("missing.txt"));
            System.out.println(text);
        } catch (NoSuchFileException e) {
            System.out.println("File not found: " + e.getFile());
        } catch (IOException e) {
            System.out.println("I/O error: " + e.getMessage());
        }
    }
}

Output:

File not found: missing.txt

Common File Operations at a Glance

import java.nio.file.*;

public class CommonOps {
    public static void main(String[] args) throws Exception {
        Path p = Path.of("sample.txt");

        // Check existence
        System.out.println(Files.exists(p));           // false

        // Create and write
        Files.writeString(p, "Line 1\nLine 2\n");

        // Check size
        System.out.println(Files.size(p) + " bytes");  // 14 bytes

        // Read all lines
        Files.readAllLines(p).forEach(System.out::println);

        // Rename / move
        Path renamed = Path.of("renamed.txt");
        Files.move(p, renamed, StandardCopyOption.REPLACE_EXISTING);

        // Copy
        Files.copy(renamed, Path.of("backup.txt"));

        // Delete
        Files.delete(renamed);
        Files.delete(Path.of("backup.txt"));
    }
}

Output:

false
14 bytes
Line 1
Line 2

In This Section

  • File Class — The classic java.io.File API for metadata, existence checks, and directory listing.
  • Create a File — Multiple ways to create new files (and directories) programmatically.
  • Read a File Line by Line — Efficient techniques for reading large text files one line at a time with BufferedReader and Files.lines().
  • Write to a File — Writing text and bytes using FileWriter, PrintWriter, and the modern Files.writeString().
  • Delete a File — Safely deleting files and directories, including non-empty directory trees.
  • RandomAccessFile — Seeking to arbitrary byte positions for reading and writing binary record-based formats.
  • Create & Read Zip Files — Compressing and extracting files with ZipOutputStream and ZipInputStream.
  • NIO.2: Path & Files — The modern java.nio.file API — paths, metadata, directory walking, symbolic links, and WatchService.
  • Java I/O — The big picture of Java’s I/O streams, from bytes to characters.
  • BufferedReader — Fast line-by-line text reading wrapped around any Reader.
  • Serialization — Persisting entire object graphs to files as binary data.
  • NIO.2: Path & Files — Modern, expressive file-system operations introduced in Java 7.
  • Exception Handling — Handling IOException and its many subclasses correctly.
  • try-catch Block — Using try-with-resources to guarantee streams are always closed.
Last updated June 13, 2026
Was this helpful?