⚡IntermediateFile I/O

Writing Files

Write text and binary data to files using Files.writeString, BufferedWriter, and PrintWriter.

Overview

Writing files in Java follows the same two-API pattern as reading: the modern java.nio.file.Files API and the classic java.io writers. Files.writeString() and Files.write() are the simplest options for most use cases. For appending to existing files or writing large amounts of data efficiently, BufferedWriter or PrintWriter wrapped in try-with-resources is the right choice. OpenOption flags (CREATE, APPEND, TRUNCATE_EXISTING) control how the file is opened.

Key Points

  • •Files.writeString(path, content) writes a String to a file, creating or replacing it
  • •Files.write(path, lines) writes a list of strings, one per line
  • •StandardOpenOption.APPEND appends to an existing file
  • •StandardOpenOption.CREATE creates the file if it does not exist
  • •BufferedWriter: efficient character output via write() and newLine()
  • •PrintWriter: adds println, printf, and format convenience methods
  • •Use try-with-resources for all writers to ensure they are flushed and closed
  • •Flushing: close() flushes automatically; call flush() if you need to write without closing

Examples

Simple file writing with Files

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

public class Main {
    public static void main(String[] args) throws IOException {
        Path path = Path.of(System.getProperty("java.io.tmpdir"), "output.txt");

        // Write a string (creates or overwrites)
        Files.writeString(path, "Hello, World!\nLine two\nLine three");
        System.out.println("Written to: " + path);

        // Verify by reading back
        System.out.println(Files.readString(path));

        // Append to existing file
        Files.writeString(path, "\nLine four (appended)", StandardOpenOption.APPEND);
        System.out.println("After append:");
        System.out.println(Files.readString(path));

        // Write a list of lines
        Path listPath = Path.of(System.getProperty("java.io.tmpdir"), "list.txt");
        Files.write(listPath, List.of("apple", "banana", "cherry"));
        Files.readAllLines(listPath).forEach(System.out::println);
    }
}

Files.writeString() is the simplest way to write a file. Pass StandardOpenOption.APPEND to add to an existing file instead of replacing it.

BufferedWriter for efficient writing

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

public class Main {
    public static void main(String[] args) throws IOException {
        Path path = Path.of(System.getProperty("java.io.tmpdir"), "buffered.txt");

        try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
            for (int i = 1; i <= 5; i++) {
                writer.write("Line " + i + ": data for row " + i);
                writer.newLine(); // platform-independent line ending
            }
        }
        // File is flushed and closed here

        Files.readAllLines(path).forEach(System.out::println);
    }
}

BufferedWriter accumulates output in memory and writes in chunks, which is much faster than writing one character at a time. newLine() writes the correct line separator for the current platform.

PrintWriter for formatted output

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

public class Main {
    record Employee(String name, String dept, double salary) {}

    public static void main(String[] args) throws IOException {
        Path path = Path.of(System.getProperty("java.io.tmpdir"), "report.txt");

        var employees = new Employee[]{
            new Employee("Alice", "Engineering", 95000),
            new Employee("Bob", "Design", 72000),
            new Employee("Carol", "Engineering", 88000),
        };

        try (PrintWriter pw = new PrintWriter(Files.newBufferedWriter(path))) {
            pw.println("Employee Report");
            pw.println("=".repeat(40));
            for (var e : employees) {
                pw.printf("%-10s %-15s $%.2f%n", e.name(), e.dept(), e.salary());
            }
            pw.printf("%n%-10s %-15s $%.2f%n", "TOTAL", "",
                java.util.Arrays.stream(employees).mapToDouble(Employee::salary).sum());
        }

        System.out.println(Files.readString(path));
    }
}

PrintWriter wraps BufferedWriter to add printf and println. It never throws IOException; call checkError() to detect errors. For strict error handling, use BufferedWriter directly.

Common Mistakes

  • Not closing the writer. Unflushed data stays in the buffer and is lost. try-with-resources calls close() which flushes first
  • Using FileWriter directly without BufferedWriter. FileWriter writes character by character, which is slow for large amounts of data
  • Overwriting a file by accident when you intended to append. The default is to create/overwrite. Pass StandardOpenOption.APPEND explicitly when appending

Note

For writing structured data like CSV or reports, PrintWriter with printf gives you excellent formatting control. For high-throughput logging, BufferedWriter with direct write() calls is fastest.

Exercises

Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.

Loading editor…

Completed: 0 / 4 exercises

Knowledge Check

Question 1 of 4

What happens when you call Files.writeString(path, content) and the file already exists?