1. 概述

本文深入解析 Java 标准库中的 FileWriter 类,它位于 java.io 包中,是处理字符文件写入的常用工具类之一。

虽然功能看似简单,但在实际开发中如果不注意编码、资源管理等问题,很容易踩坑。尤其在跨平台或涉及中文字符时,稍不注意就会出现乱码或文件写入失败。

2. FileWriter 简介

FileWriterOutputStreamWriter 的子类,专用于向文件写入字符数据
❌ 它本身不提供新的写入方法,所有操作都继承自 WriterOutputStreamWriter

在 Java 11 之前,FileWriter 只能使用默认字符集(通常是系统平台默认,如 Windows 的 GBK,Linux/Unix 的 UTF-8)和固定大小的缓冲区(8192 字节)。

⚠️ 从 Java 11 开始,新增了支持指定 Charset 的构造函数,解决了长期以来无法自定义编码的问题,但缓冲区大小仍不可调,固定为 8192。

2.1 创建 FileWriter 实例

在 Java 11 之前,FileWriter 提供了 5 个构造函数:

public FileWriter(String fileName) throws IOException {
    super(new FileOutputStream(fileName));
}

public FileWriter(String fileName, boolean append) throws IOException {
    super(new FileOutputStream(fileName, append));
}

public FileWriter(File file) throws IOException {
    super(new FileOutputStream(file));
}

public FileWriter(File file, boolean append) throws IOException {
    super(new FileOutputStream(file, append));
}

public FileWriter(FileDescriptor fd) {
    super(new FileOutputStream(fd));
}

Java 11 新增了 4 个支持指定字符集的构造函数:

public FileWriter(String fileName, Charset charset) throws IOException {
    super(new FileOutputStream(fileName), charset);
}

public FileWriter(String fileName, Charset charset, boolean append) throws IOException {
    super(new FileOutputStream(fileName, append), charset);
}

public FileWriter(File file, Charset charset) throws IOException {
    super(new FileOutputStream(file), charset);
}

public FileWriter(File file, Charset charset, boolean append) throws IOException {
    super(new FileOutputStream(file, append), charset);
}

📌 关键点总结:

  • 所有构造函数底层都依赖 FileOutputStream
  • append 参数控制是否追加写入(true 表示追加)
  • Java 11 前无法指定编码,容易导致乱码问题(尤其是中文)
  • 使用 Charset 构造函数可避免平台默认编码带来的兼容性问题

2.2 写入字符串到文件

使用 FileWriter 写入字符串非常简单,推荐结合 try-with-resources 自动管理资源:

try (FileWriter fileWriter = new FileWriter("src/test/resources/FileWriterTest.txt")) {
    fileWriter.write("Hello Folks!");
}

执行后,文件内容为:

Hello Folks!

📌 注意事项:

  • FileWriter 实现了 AutoCloseable,使用 try-with-resources 可自动关闭流,避免资源泄漏
  • ⚠️ 不保证文件一定能创建成功,具体行为依赖底层操作系统。例如某些系统可能因权限问题导致创建失败
  • ❌ 某些平台(如 Windows)对文件独占锁较严格,同一时间只能有一个 FileWriter 打开该文件,否则会抛出 IOException

💡 建议:生产环境务必捕获 IOException,并做好异常日志记录。

2.3 向文件追加内容

很多时候我们不希望覆盖原文件,而是追加内容。这时只需将 append 参数设为 true

try (FileWriter fileWriter = new FileWriter("src/test/resources/FileWriterTest.txt", true)) {
    fileWriter.write("Hello Folks Again!");
}

执行后,文件内容变为:

Hello Folks!Hello Folks Again!

📌 追加模式要点:

  • 第二个参数 true 表示以追加方式打开文件
  • 如果文件不存在,仍会自动创建
  • 多次追加不会自动换行,如需换行需手动添加 \n 或使用 newLine() 方法

💡 小技巧:若要换行追加,可这样写:

fileWriter.write("Hello Folks Again!\n");

3. 总结

FileWriter 是一个简单粗暴的字符文件写入工具,适合快速实现文本写入需求。但在实际项目中需要注意以下几点:

  • ✅ Java 11+ 推荐使用带 Charset 的构造函数,明确指定编码(如 StandardCharsets.UTF_8),避免乱码
  • ✅ 必须使用 try-with-resources 管理资源
  • ⚠️ 注意平台兼容性问题,尤其是文件锁和默认编码
  • 🚫 不适用于大文件写入(无缓冲优化),建议结合 BufferedWriter 使用

示例完整代码已托管至 GitHub: https://github.com/baeldung/core-java-modules/tree/master/core-java-io-apis

对于更复杂的 I/O 操作,建议考虑 Files.write()BufferedWriter 配合 OutputStreamWriter 的方式,灵活性和性能更优。


原始标题:Java FileWriter | Baeldung