Skip to content
Java io 7 min read

FileWriter

FileWriter is Java’s simplest way to write character data to a file. It converts your text into bytes using a character encoding and streams them straight to disk — no extra setup required for most everyday file-writing tasks.

Filewriter writer class hierarchy

What Is FileWriter?

FileWriter lives in java.io and extends OutputStreamWriter, which itself extends Writer. It is a convenience class that combines a FileOutputStream and an OutputStreamWriter under the hood, saving you the boilerplate of wiring them together manually.

The class hierarchy looks like this:

java.io.Writer
  └── java.io.OutputStreamWriter
        └── java.io.FileWriter

Because it is a character stream, it works with char, char[], and String — not raw bytes. If you need to write binary data, reach for FileOutputStream instead. For a comparison of the two stream families, see Byte vs Character Streams.

Writing to a File

The most basic usage: create a FileWriter, write some text, and close it.

import java.io.FileWriter;
import java.io.IOException;

public class BasicFileWriterDemo {
    public static void main(String[] args) throws IOException {
        try (FileWriter fw = new FileWriter("hello.txt")) {
            fw.write("Hello, Java FileWriter!\n");
            fw.write("Writing is easy.");
        }
        System.out.println("File written successfully.");
    }
}

Output:

File written successfully.

After running this, hello.txt contains:

Hello, Java FileWriter!
Writing is easy.

Tip: Always use try-with-resources (Java 7+). It calls close() automatically — even when an exception is thrown — which flushes any buffered data and releases the file handle.

Constructors

FileWriter gives you several constructors depending on whether you have a path string or a File object, and whether you want append mode:

ConstructorDescription
FileWriter(String fileName)Creates/overwrites the file at the given path
FileWriter(String fileName, boolean append)append = true keeps existing content
FileWriter(File file)Same as string path, but takes a File object
FileWriter(File file, boolean append)File + append mode
FileWriter(String fileName, Charset charset)Explicit charset (Java 11+)
FileWriter(File file, Charset charset, boolean append)File + charset + append (Java 11+)

Warning: Without the append flag (or with append = false), opening an existing file silently overwrites all its contents. Double-check which mode you need before writing to production files.

Append Mode

Passing true as the second constructor argument tells FileWriter to start writing at the end of any existing content rather than replacing it:

import java.io.FileWriter;
import java.io.IOException;

public class AppendDemo {
    public static void main(String[] args) throws IOException {
        // First run creates the file
        try (FileWriter fw = new FileWriter("log.txt", true)) {
            fw.write("First entry\n");
        }

        // Second run adds to it instead of replacing it
        try (FileWriter fw = new FileWriter("log.txt", true)) {
            fw.write("Second entry\n");
        }

        System.out.println("Entries appended.");
    }
}

Output:

Entries appended.

log.txt will contain both lines after the second run.

The write() Methods

FileWriter inherits all Writer write methods:

import java.io.FileWriter;
import java.io.IOException;

public class WriteMethodsDemo {
    public static void main(String[] args) throws IOException {
        try (FileWriter fw = new FileWriter("methods.txt")) {
            // Write a single character (as an int code point)
            fw.write(65);                          // writes 'A'

            // Write a char array
            char[] chars = {'J', 'a', 'v', 'a'};
            fw.write(chars);                       // writes "Java"

            // Write a portion of a char array
            fw.write(chars, 1, 3);                 // writes "ava"

            // Write a String
            fw.write(" rocks!\n");

            // Write a portion of a String
            fw.write("Hello World", 0, 5);         // writes "Hello"
        }
    }
}

After running, methods.txt contains:

AJavaava rocks!
Hello

flush() vs close()

FileWriter may buffer a small amount of data internally (inherited from OutputStreamWriter). Calling flush() pushes any buffered characters to the OS immediately without closing the stream. close() flushes and then releases the file handle.

import java.io.FileWriter;
import java.io.IOException;

public class FlushDemo {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("progress.txt");
        try {
            fw.write("Step 1 done\n");
            fw.flush();   // make sure step 1 is visible on disk now

            fw.write("Step 2 done\n");
            fw.flush();
        } finally {
            fw.close();   // also flushes, but safe to call after flush()
        }
    }
}

Note: In most applications you will rely on close() (or try-with-resources) rather than calling flush() explicitly. Manual flush() is useful when you want to ensure crash-safety at checkpoints in a long-running write operation.

Character Encoding

Before Java 11, FileWriter always used the platform default charset — whatever Charset.defaultCharset() returned on that machine. This made code behave differently across operating systems (e.g., Windows vs Linux), which could corrupt files containing non-ASCII characters.

Java 11+ added constructors that accept an explicit Charset:

import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class EncodingDemo {
    public static void main(String[] args) throws IOException {
        // Always specify UTF-8 for portable, correct text output
        try (FileWriter fw = new FileWriter("unicode.txt",
                StandardCharsets.UTF_8)) {
            fw.write("Héllo Wörld — 你好 — مرحبا\n");
        }
        System.out.println("UTF-8 file written.");
    }
}

Tip: If you are on Java 8–10, wrap a FileOutputStream with an OutputStreamWriter instead to get explicit encoding control:

new OutputStreamWriter(new FileOutputStream("file.txt"), StandardCharsets.UTF_8)

This is exactly what FileWriter does internally anyway.

Wrapping With BufferedWriter

FileWriter writes to disk one or a few characters at a time, which can mean many system calls for a large document. Wrapping it with BufferedWriter collects characters in an 8 KB buffer and flushes in large chunks — much faster for bulk output.

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("data.txt"))) {
            for (int i = 1; i <= 5; i++) {
                bw.write("Line " + i);
                bw.newLine();   // platform-independent line separator
            }
        }
        System.out.println("Buffered write done.");
    }
}

Output:

Buffered write done.

data.txt:

Line 1
Line 2
Line 3
Line 4
Line 5

bw.newLine() writes \n on Unix and \r\n on Windows — better than hardcoding "\n" if you care about portability.

Practical Example: Writing a CSV File

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class CsvWriterDemo {
    public static void main(String[] args) throws IOException {
        String[][] data = {
            {"Name",  "Age", "City"},
            {"Alice", "30",  "London"},
            {"Bob",   "25",  "Toronto"},
            {"Carol", "35",  "Sydney"},
        };

        try (BufferedWriter bw = new BufferedWriter(
                new FileWriter("people.csv", StandardCharsets.UTF_8))) {
            for (String[] row : data) {
                bw.write(String.join(",", row));
                bw.newLine();
            }
        }
        System.out.println("CSV written.");
    }
}

Output:

CSV written.

people.csv:

Name,Age,City
Alice,30,London
Bob,25,Toronto
Carol,35,Sydney

Under the Hood

When you construct FileWriter("output.txt"), Java internally does:

  1. Creates a FileOutputStream pointing to output.txt (creating the file if absent, truncating if not in append mode).
  2. Wraps it in the StreamEncoder — a sun.nio.cs class that converts char values to bytes using the chosen Charset (a CharsetEncoder under the covers).
  3. Exposes the resulting byte pipeline through the Writer API.

Each call to write(String s) encodes the characters in s into a byte array and hands it to the underlying FileOutputStream. Without BufferedWriter, each write() call may translate to one or more OS write syscalls, which involve a kernel-mode transition and are relatively expensive. Wrapping with BufferedWriter batches those syscalls significantly.

The close() method first calls flush() to drain any remaining bytes from the StreamEncoder’s internal partial-character state (important for multi-byte encodings like UTF-8), then closes the FileOutputStream, which releases the OS file descriptor.

Note: FileWriter is not thread-safe. If multiple threads write to the same FileWriter concurrently, characters from different threads can interleave. Use synchronized blocks, a PrintWriter with explicit synchronization, or write from a single dedicated thread.

FileWriter vs Other Write Options

OptionBest For
FileWriterSimple text output, quick scripts
BufferedWriter(new FileWriter(...))Text output with better performance
PrintWriter(new FileWriter(...))Formatted text output (printf, println)
Files.writeString(path, text) (NIO, Java 11+)One-shot writes with explicit charset
Files.write(path, lines) (NIO)Writing a collection of lines at once

For new code on Java 11+, Files.writeString() or Files.write() from NIO.2 are often more concise. FileWriter and BufferedWriter remain valuable when you need a streaming Writer interface — for example, to pass to a serializer or template engine.

Last updated June 13, 2026
Was this helpful?