FileWriter 是 Java I/O 库中一个用于将字符写入文件的便捷类,它是 Writer 类的一个直接子类,专门设计用来处理字符流,而不是字节流。

FileWriter 是什么?
FileWriter 的主要作用是将字符数据(如 String)直接写入到文件中,它内部会处理字符到字节的转换(通常是使用平台的默认字符编码,如 UTF-8, GBK 等),然后通过操作系统将字节写入文件。
核心特点:
- 字符流:它操作的是
char类型的数据,而不是byte,这使得处理文本文件更加方便。 - 便捷性:它简化了文件写入的流程,你不需要像使用
FileOutputStream那样手动进行字符编码转换。 - 覆盖 vs 追加:创建
FileWriter实例时,可以选择是覆盖文件原有内容,还是在文件末尾追加内容。 - 自动刷新:默认情况下,数据是先写入缓冲区的,需要调用
flush()方法或关闭流时才会真正写入文件。
如何使用 FileWriter (基本用法)
使用 FileWriter 的标准步骤如下:
- 创建
FileWriter对象:指定要写入的文件路径,如果文件不存在,它会自动创建;如果文件已存在,根据构造函数参数决定是覆盖还是追加。 - 写入数据:调用
write()方法写入字符、字符串或字符数组。 - 刷新缓冲区 (可选):调用
flush()方法,确保所有缓冲区的数据都被写入文件。 - 关闭流:调用
close()方法。这一步至关重要,它会释放系统资源,并确保所有数据都被刷新到文件中,推荐使用try-with-resources语句来自动关闭流。
构造函数详解
FileWriter 提供了几个构造函数,以适应不同的需求:

| 构造函数 | 描述 |
|---|---|
FileWriter(String fileName) |
创建一个 FileWriter,使用给定的文件名,如果文件已存在,将被覆盖。 |
FileWriter(String fileName, boolean append) |
创建一个 FileWriter。append 参数为 true 时,数据将写入文件末尾(追加);为 false 时,将覆盖文件内容。 |
FileWriter(File file) |
创建一个 FileWriter,使用给定的 File 对象,如果文件已存在,将被覆盖。 |
FileWriter(File file, boolean append) |
创建一个 FileWriter,使用给定的 File 对象。append 参数含义同上。 |
FileWriter(String fileName, Charset charset) |
(Java 11+) 创建一个 FileWriter,并显式指定字符编码,而不是使用平台默认编码。 |
FileWriter(File file, Charset charset) |
(Java 11+) 创建一个 FileWriter,并显式指定字符编码。 |
重要提示:在 Java 11 之前,FileWriter 总是使用 JVM 默认的字符编码,这在跨平台时可能会导致问题(Windows 默认可能是 GBK,而 Linux/macOS 默认是 UTF-8),从 Java 11 开始,推荐使用带有 Charset 参数的构造函数来明确指定编码,以确保文件的可移植性。
代码示例
示例 1:基本写入(覆盖模式)
这是最简单的用法,会覆盖文件中的所有内容。
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
String filePath = "my_file.txt";
String content = "你好,世界!\nThis is a test for FileWriter.";
try (FileWriter writer = new FileWriter(filePath)) {
// 写入一个字符串
writer.write(content);
// 写入一个字符
writer.write('\n');
// 写入一个字符数组
char[] charArray = "Hello, FileWriter!".toCharArray();
writer.write(charArray);
System.out.println("文件写入成功!");
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
// try-with-resources 会自动关闭 writer
}
}
执行后,my_file.txt 文件内容将是:
你好,世界!
This is a test for FileWriter.
Hello, FileWriter!
示例 2:追加模式
如果希望在文件现有内容的基础上添加新内容,应该使用追加模式。

import java.io.FileWriter;
import java.io.IOException;
public class FileWriterAppendExample {
public static void main(String[] args) {
String filePath = "my_file.txt";
String newContent = "\nThis is a new line appended to the file.";
try (FileWriter writer = new FileWriter(filePath, true)) { // 注意第二个参数 true
writer.write(newContent);
System.out.println("内容追加成功!");
} catch (IOException e) {
System.err.println("追加文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
my_file.txt 已存在,运行此代码后,其内容会在原有内容末尾添加新的一行。
示例 3:显式指定字符编码 (Java 11+)
这是推荐的最佳实践,可以避免因平台默认编码不同而导致的乱码问题。
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class FileWriterEncodingExample {
public static void main(String[] args) {
String filePath = "my_utf8_file.txt";
String content = "使用 UTF-8 编码写入文件。";
try (FileWriter writer = new FileWriter(filePath, StandardCharsets.UTF_8)) {
writer.write(content);
System.out.println("使用 UTF-8 编码写入文件成功!");
} catch (IOException e) {
System.err.println("写入文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
FileWriter 的局限性与最佳实践
局限性:
- 性能问题:
FileWriter本身不带缓冲区,每次调用write()方法都可能直接进行磁盘 I/O 操作,这非常低效。 - 编码问题 (Java 11前):容易因平台默认编码不一致导致乱码。
最佳实践:
-
使用
BufferedWriter包装FileWriter为了提高性能,强烈建议将FileWriter用BufferedWriter包装起来。BufferedWriter内部有一个缓冲区(默认大小通常是 8KB),数据会先写入内存缓冲区,当缓冲区满了或调用flush()时,才会一次性写入磁盘,大大减少了 I/O 操作次数。import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class BestPracticeExample { public static void main(String[] args) { String filePath = "best_practice.txt"; String content = "这是一个使用 BufferedWriter 优化的例子。"; try (FileWriter fw = new FileWriter(filePath); BufferedWriter bw = new BufferedWriter(fw)) { bw.write(content); bw.newLine(); // BufferedWriter 提供了便捷的换行方法 bw.write("这是第二行。"); // bw.flush(); // 在 close() 之前,可以手动调用 flush() // try-with-resources 会自动调用 close(),而 close() 会自动调用 flush() } catch (IOException e) { e.printStackTrace(); } } } -
始终使用
try-with-resourcesFileWriter和BufferedWriter都实现了AutoCloseable接口,使用try-with-resources语句可以确保无论是否发生异常,流都会被正确关闭,避免资源泄漏。 -
(Java 11+)指定字符编码 如前所述,在创建
FileWriter时,总是显式传入Charset对象(如StandardCharsets.UTF_8)。
FileWriter vs. FileOutputStream
这是一个常见的问题,理解它们的区别很重要。
| 特性 | FileWriter |
FileOutputStream |
|---|---|---|
| 数据类型 | 字符流 (Writer),处理 char |
字节流 (OutputStream),处理 byte |
| 用途 | 专门用于写入文本文件 | 用于写入任何类型的数据,包括文本、图片、音频等 |
| 编码 | 内部处理字符到字节的转换 | 直接写入字节,不进行任何转换 |
| 适用场景 | 写入 .txt, .csv, .json, .xml 等纯文本文件 |
写入二进制文件(如 .jpg, .mp3),或需要精确控制字节时写入文本文件 |
| 性能 | 较慢(需转换),建议用 BufferedWriter 包装 |
较快(直接操作字节),建议用 BufferedOutputStream 包装 |
如果你的目标是写入人类可读的文本文件,请优先选择 FileWriter(并用 BufferedWriter 包装),如果目标是写入二进制数据,或者对字节有精确的控制要求,请使用 FileOutputStream(并用 BufferedOutputStream 包装)。
