Java File Handling Explained with Examples

Java file handling includes creating entries, reading content, writing or appending content, and deleting entries when their lifecycle is complete.

Lesson 69 of 127Intermediate12 min read

Java file handling includes creating entries, reading content, writing or appending content, and deleting entries when their lifecycle is complete. Path represents a location, while Files provides operations on that location. This lesson uses UTF-8 text and temporary fixtures so every complete example can run without overwriting a reader's documents. Learn the behavior of each operation before applying it to a real file. In particular, replacing content, appending content, closing a stream, and deleting a file are different actions.

Create a file with an explicit existence policy

Files.createFile creates a new empty file and fails when that entry already exists. It is not the same as merely constructing a Path, which performs no creation. The parent directory must exist. For an application, decide whether an existing file should be rejected, reused, or replaced; do not select an overwrite behavior casually. The first example creates its parent as a new temporary directory so the expected creation path is isolated.

Read text with a stated encoding

Files.readString reads an entire text file into a String, using UTF-8 by default or an explicit supplied charset. Files.readAllLines produces a list of lines. Both are convenient for modest files but load their contents into memory. For large inputs, use a buffered reader or streaming approach with proper closure. Reading can fail because the file is absent, inaccessible, or invalid under a selected decoding contract. Keep these failures distinct from an empty but valid file.

Writing can replace existing content

Files.writeString with its ordinary default options creates a missing file or truncates an existing file before writing. Truncation discards previous content, so state that policy in the application's requirements. Supply the encoding explicitly when interoperability matters. A successful write does not imply the application has implemented a crash-safe transaction or verified every consumer's format. For durable replacement requirements, use a documented staging and move strategy appropriate to the filesystem.

Append without recreating old content

StandardOpenOption.APPEND requests adding content at the end instead of truncating it. Include separators such as newlines yourself; Java does not invent a record boundary between two arbitrary strings. When appending to a potentially missing file, combine an appropriate CREATE policy with APPEND. Multiple concurrent writers need a coordination design; APPEND alone is not a general cross-platform transaction guarantee for whole application records.

Delete according to a useful result contract

Files.delete throws when deletion fails, including when the expected file does not exist. Files.deleteIfExists returns false for absence and true when it deletes an existing entry, while other failures can still throw. Removing a directory normally requires it to be empty. Closing an open reader or writer releases resources but does not remove the stored file. Never treat a successful close as proof that deletion occurred.

Own fixtures and handle failures meaningfully

The examples delete only temporary files and directories they created. In a real program, identify which component owns cleanup and whether data must remain for later use. Preserve useful IOException causes when reporting failure, and do not announce a completed export after a failed write. Review try-with-resources for explicit stream ownership and Path and Files for listing, copying, and other directory operations.

Practice tasks and checks

Create a temporary file, write two lines, and verify the exact reloaded content. Repeat with a second ordinary write and observe truncation, then restore APPEND and explain the difference. Add a non-ASCII word and keep the charset consistent across writing and reading. Test creation when the owned entry already exists and classify that outcome separately from malformed text. For deletion, compare deleteIfExists on an absent entry with delete on an expected existing entry. Keep cleanup restricted to the fixtures you created. Finally, write a small export contract stating whether an existing destination may be overwritten and what the application reports when writing fails. These policies are part of file handling, not incidental options.

Java Summary

  • A Path describes a location without creating its entry.
  • Default writing and APPEND have different content-preservation policies.
  • Closing resources and deleting stored files are separate actions.
  • Continue with Path and directory operations when these examples are clear.

Java Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Create an empty file in an isolated directory

Save this program as CreateFileExample.java. Compile it with javac CreateFileExample.java and run it with java CreateFileExample.

Expected output:

resolve describes the child location without touching storage. createFile then creates the entry, so exists becomes true. Its byte size is zero because no content has been written. The finally block removes the owned file before its parent directory. If createFile fails, deleteIfExists tolerates a missing child during cleanup; other deletion failures remain visible rather than being silently ignored.

Java
import java.nio.file.Files;
import java.nio.file.Path;
public class CreateFileExample {
    public static void main(String[] args) throws Exception {
        Path directory = Files.createTempDirectory("file-create-");
        Path note = directory.resolve("note.txt");
        try {
            Files.createFile(note);
            System.out.println(Files.exists(note));
            System.out.println(Files.size(note));
        } finally {
            Files.deleteIfExists(note);
            Files.delete(directory);
        }
    }
}
Output
true
0
Example 2

Write, append, and read UTF-8 text

Save this program as TextFileLifecycle.java. Compile it with javac TextFileLifecycle.java and run it with java TextFileLifecycle.

Expected output:

The first write replaces the initially empty fixture with one newline-terminated record. The APPEND option adds the second record after it, preserving the first. readString returns both lines under the same UTF-8 contract, and print avoids adding an unrelated extra newline. Removing APPEND from the second write would truncate the first record instead. The finally block deletes the fixture after the content has been observed.

Java
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class TextFileLifecycle {
    public static void main(String[] args) throws Exception {
        Path file = Files.createTempFile("stock-note-", ".txt");
        try {
            Files.writeString(file, "Seed stock: 18\n", StandardCharsets.UTF_8);
            Files.writeString(file, "Checked by Mina\n", StandardCharsets.UTF_8,
                StandardOpenOption.APPEND);
            System.out.print(Files.readString(file, StandardCharsets.UTF_8));
        } finally {
            Files.deleteIfExists(file);
        }
    }
}
Output
Seed stock: 18
Checked by Mina
Example 3

Distinguish deleted from already absent

Save this program as DeleteFileExample.java. Compile it with javac DeleteFileExample.java and run it with java DeleteFileExample.

Expected output:

The first call finds and removes the temporary entry, returning true. The second sees no entry and returns false without treating that absence as an exceptional failure. The final cleanup call is intentionally safe under the same absence policy. deleteIfExists can still throw for other filesystem failures, so this result contract does not mean deletion is infallible or that all permission problems should be ignored.

Java
import java.nio.file.Files;
import java.nio.file.Path;
public class DeleteFileExample {
    public static void main(String[] args) throws Exception {
        Path file = Files.createTempFile("delete-note-", ".txt");
        try {
            System.out.println(Files.deleteIfExists(file));
            System.out.println(Files.deleteIfExists(file));
        } finally {
            Files.deleteIfExists(file);
        }
    }
}
Output
true
false

Java FAQ

Does new File or Path.of create a file?

No. Those expressions describe a pathname through their respective APIs. A creation or writing operation must actually create the filesystem entry. A represented path can remain nonexistent.

Why state UTF-8 explicitly if it is the default here?

It makes the file's interchange contract visible to readers and related tools. Consistent encoding matters when another component writes or reads the same data, especially with non-ASCII text.

How do I create a file only if it doesn't already exist?

Call Files.createFile(path) and catch FileAlreadyExistsException. The check and the creation happen as one operation, which is safer than calling Files.exists first, because another program can create the file in between.

How do I delete a folder that isn't empty?

Files.delete only removes empty folders. Walk the tree with Files.walk(folder), sort the paths in reverse order so files and subfolders come before their parents, and delete each one. Double-check the starting path first, because this permanently removes everything inside it.

How do I overwrite a file without risking a half-written result?

Write the new content to a temporary file in the same folder, then move it over the original with Files.move(temp, target, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE). If the program crashes during the write, the original file is still intact.

Java Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choiceeasy

What does createFile do when the entry already exists?

Multiple choicemedium

What keeps the first line during the second write?

Java Quiz

2 questions to check what you learned.

  1. What does the second deleteIfExists return in the example?

    • false
    • true
    • The deleted file contents
  2. When is reading the entire file into a String inappropriate?

    • When the input can be too large for the memory policy
    • Whenever UTF-8 is used
    • Only when the filename ends in txt