Skip to content

FileWriter 文件字符写入

有些人写日志用 FileWriter,有些人用 OutputStreamWriter

表面上看,FileWriter 短了一截。但当你的应用跑在 Windows 服务器上,日志文件用 GBK 编码;而另一套 Linux 系统用 UTF-8 读取时——你就会明白那几行代码省的是什么。

基本用法

写入模式

java
// 覆盖模式(默认)
FileWriter fw = new FileWriter("output.txt");

// 追加模式
FileWriter fw = new FileWriter("output.txt", true);

// File 对象
FileWriter fw = new FileWriter(new File("output.txt"));

// File 对象 + 追加模式
FileWriter fw = new FileWriter(new File("output.txt"), true);

第二个参数 true 表示追加模式,false(默认)是覆盖模式。

写入操作

java
// 单字符写入
try (FileWriter fw = new FileWriter("output.txt")) {
    fw.write(65);              // 写入字符 'A'
    fw.write('\n');
    fw.write("你好 Java");     // 直接写字符串
}

// 字符数组写入
try (FileWriter fw = new FileWriter("output.txt")) {
    char[] chars = {'H', 'e', 'l', 'l', 'o'};
    fw.write(chars);
    fw.write("\n");
    fw.write(chars, 0, 3);     // 写前 3 个字符:Hel
}

FileWriter 的问题:无法指定编码

FileReader 一样,FileWriter 有一个致命缺陷:不能指定字符编码

java
// ❌ 问题:依赖平台默认编码
FileWriter fw = new FileWriter("output.txt");
// Windows 用 GBK 写入,macOS 用 UTF-8 读取 → 乱码

// ✅ 正确:用 OutputStreamWriter + 指定编码
try (BufferedWriter writer = new BufferedWriter(
        new OutputStreamWriter(
            new FileOutputStream("output.txt"), StandardCharsets.UTF_8))) {
    writer.write("你好 Java");
}

追加写入的正确姿势

java
// 追加模式:保留原有内容
try (FileWriter fw = new FileWriter("log.txt", true)) {
    fw.write("New log entry at " + System.currentTimeMillis() + "\n");
}
// 多次运行,log.txt 的内容会越来越多

BufferedWriter 的加持

java
// BufferedWriter:加缓冲 + newLine()
try (
    BufferedWriter writer = new BufferedWriter(
        new FileWriter("output.txt"))
) {
    writer.write("第一行");
    writer.newLine(); // 平台无关的换行符
    writer.write("第二行");
    writer.newLine();
    writer.flush();
}
// newLine() 自动适配:Windows → \r\n,Linux/macOS → \n

newLine() 的作用

平台newLine() 写入write("\n") 写入
Windows\r\n\n(不一致!)
Linux / macOS\n\n(一致)

对比:FileWriter vs OutputStreamWriter

特性FileWriterOutputStreamWriter
指定编码❌ 不支持✅ 支持
内部实现直接用默认编码包装字节流 + 编码器
适用场景纯英文、快速原型生产环境、多语言
java
// ❌ FileWriter:不能指定编码
try (FileWriter fw = new FileWriter("output.txt")) {
    fw.write("你好");
} // 依赖系统默认编码,可能乱码

// ✅ OutputStreamWriter:可以指定编码
try (
    BufferedWriter writer = new BufferedWriter(
        new OutputStreamWriter(
            new FileOutputStream("output.txt"), StandardCharsets.UTF_8))
) {
    writer.write("你好");
}

// ✅ JDK 11+ 最简写法
Files.writeString(Path.of("output.txt"), "你好", StandardCharsets.UTF_8);

常见问题

目录不存在

java
// ❌ 目录不存在会抛异常
new FileWriter("/nonexistent/dir/file.txt");

// ✅ 先创建目录
File file = new File("/nonexistent/dir/file.txt");
file.getParentFile().mkdirs();
try (FileWriter fw = new FileWriter(file)) {
    fw.write("content");
}

write() vs append()

java
// 效果相同,但 append() 返回 Writer,支持链式调用
fw.write("Hello");
fw.append("Hello").append(" ").append("World");

记住这个原则

FileWriter 写英文,OutputStreamWriter 写世界。 生产环境永远指定编码,永远用 BufferedWriter。

基于 VitePress 构建