Write to a File
Writing to a file is one of the most common tasks in Java — whether you’re saving application logs, exporting data, or persisting configuration. Java gives you several APIs to do it, ranging from the classic java.io streams to the modern java.nio.file.Files helpers. This page walks through each approach so you can pick the right one for your situation.
Using FileWriter
FileWriter is the simplest way to write text to a file. It opens (or creates) a file and lets you write String data directly.
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
try (FileWriter fw = new FileWriter("output.txt")) {
fw.write("Hello, Java!\n");
fw.write("Writing to a file is easy.");
System.out.println("File written successfully.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output:
File written successfully.
output.txt will contain:
Hello, Java!
Writing to a file is easy.
Note: The
try-with-resourcesblock automatically closes the writer, flushing any buffered data. Always use it to avoid resource leaks.
Warning: By default,
FileWriteroverwrites an existing file. To append instead, usenew FileWriter("output.txt", true).
Using BufferedWriter (Recommended for Text)
Wrapping a FileWriter in a BufferedWriter batches writes in memory before flushing to disk. This is significantly faster when writing many lines, because it reduces the number of actual OS write calls.
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterExample {
public static void main(String[] args) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("log.txt"))) {
bw.write("Line 1: Application started");
bw.newLine();
bw.write("Line 2: Processing data...");
bw.newLine();
bw.write("Line 3: Done.");
System.out.println("Log file written.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
bw.newLine() writes the platform-appropriate line separator (\n on Linux/macOS, \r\n on Windows), making your output portable.
Tip: Prefer
BufferedWriterover bareFileWriterwhenever you write more than one line. The internal buffer (default 8 KB) makes a noticeable difference in performance.
Appending to an Existing File
Both FileWriter and BufferedWriter support an append flag. Pass true as the second constructor argument:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class AppendToFile {
public static void main(String[] args) {
// Appends to "log.txt" instead of overwriting it
try (BufferedWriter bw = new BufferedWriter(new FileWriter("log.txt", true))) {
bw.write("New log entry appended.");
bw.newLine();
System.out.println("Entry appended.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using PrintWriter
PrintWriter adds println(), printf(), and format() methods on top of FileWriter, making it feel like writing to System.out. It’s a great fit for formatted text output.
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterExample {
public static void main(String[] args) {
try (PrintWriter pw = new PrintWriter(new FileWriter("report.txt"))) {
pw.println("=== Sales Report ===");
pw.printf("%-15s %10s%n", "Product", "Revenue");
pw.printf("%-15s %10.2f%n", "Widget A", 4250.75);
pw.printf("%-15s %10.2f%n", "Gadget B", 8120.00);
System.out.println("Report written.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
report.txt content:
=== Sales Report ===
Product Revenue
Widget A 4250.75
Gadget B 8120.00
Warning:
PrintWriterswallowsIOExceptionsilently by default. Callpw.checkError()after writing to detect failures, or wrap aFileWriterinside it as shown above so the outertry-catchstays in play.
Using FileOutputStream (Binary / Byte-Level Writing)
When you need to write raw bytes — images, serialized data, or any binary content — use FileOutputStream directly.
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamExample {
public static void main(String[] args) {
byte[] data = "Binary data: Hello".getBytes();
try (FileOutputStream fos = new FileOutputStream("data.bin")) {
fos.write(data);
System.out.println("Bytes written: " + data.length);
} catch (IOException e) {
e.printStackTrace();
}
}
}
For text written as bytes, explicitly specify a charset to avoid platform-dependent encoding:
fos.write("Hello, World!".getBytes(java.nio.charset.StandardCharsets.UTF_8));
Using NIO Files.write() and Files.writeString() (Java 7+ / Java 11+)
The modern java.nio.file.Files class offers convenient one-liner methods that handle opening, writing, and closing for you. For more on the NIO.2 API, see NIO.2: Path & Files.
Files.write() — write a list of lines (Java 7+)
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class NioWriteLines {
public static void main(String[] args) throws IOException {
List<String> lines = List.of("Alpha", "Beta", "Gamma");
Path path = Path.of("items.txt");
Files.write(path, lines, StandardCharsets.UTF_8);
System.out.println("Lines written: " + lines.size());
}
}
Files.writeString() — write a single string (Java 11+)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class NioWriteString {
public static void main(String[] args) throws IOException {
String content = "This is the entire file content.\nSecond line here.";
Files.writeString(Path.of("note.txt"), content);
System.out.println("File written.");
}
}
Appending with NIO
Pass StandardOpenOption.APPEND to avoid overwriting:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class NioAppend {
public static void main(String[] args) throws IOException {
Files.writeString(
Path.of("note.txt"),
"\nAppended line.",
StandardOpenOption.APPEND
);
System.out.println("Appended.");
}
}
Tip: For small files that fit comfortably in memory,
Files.writeString()is the cleanest option available in modern Java. For large files or streaming scenarios, stick withBufferedWriter.
Choosing the Right Approach
| Scenario | Recommended API |
|---|---|
| Simple text file (small) | Files.writeString() (Java 11+) |
| Write many lines of text | BufferedWriter wrapping FileWriter |
Formatted text (printf-style) | PrintWriter |
| List of lines at once | Files.write(path, lines, charset) |
| Raw binary / byte data | FileOutputStream (optionally buffered) |
| Append to existing log file | Any writer with append = true flag |
Under the Hood
When you write to a file in Java, data travels through several layers before hitting physical storage:
- Java layer — your
write()call fills a byte buffer inside the writer object. - JVM / OS boundary — when the buffer is full (or
flush()/close()is called), the JVM issues awrite()syscall, transferring data to the OS kernel page cache. - Kernel page cache — the OS keeps the data in memory and marks those pages as “dirty.” The kernel’s pdflush / writeback threads periodically flush dirty pages to disk.
- Physical storage — data is finally written to the storage device.
This means that even after close() returns, your data may still be in the OS cache and not durably on disk. For mission-critical durability (e.g., financial records), call FileOutputStream.getFD().sync() or open the file with StandardOpenOption.SYNC / StandardOpenOption.DSYNC to force an fsync syscall.
BufferedWriter adds an extra in-process buffer (typically 8 192 bytes) between your code and the OS. Writing 10 000 one-character strings without BufferedWriter generates 10 000 syscalls; with BufferedWriter it might generate as few as two. The performance difference is real and measurable.
Encoding also matters. FileWriter in Java 11 and earlier defaults to the platform default charset, which varies between Windows (often CP-1252) and Linux (UTF-8). From Java 17 the no-arg FileWriter(String) constructor still uses the default charset, so always pass an explicit charset when portability matters:
new FileWriter("file.txt", java.nio.charset.StandardCharsets.UTF_8)
Or use Files.writeString(), which always defaults to UTF-8.
Related Topics
- Create a File — create a file before writing to it with
Files.createFile()and more - Read a File Line by Line — read back what you wrote using
BufferedReaderand NIO - BufferedWriter — deep dive into buffered character output
- FileOutputStream — byte-level output for binary files
- PrintWriter — formatted text output with
printf()andprintln() - NIO.2: Path & Files — the modern filesystem API powering
Files.writeString()