杰瑞科技汇

Java FileWriter如何正确使用与关闭?

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

Java FileWriter如何正确使用与关闭?-图1
(图片来源网络,侵删)

FileWriter 是什么?

FileWriter 的主要作用是将字符数据(如 String)直接写入到文件中,它内部会处理字符到字节的转换(通常是使用平台的默认字符编码,如 UTF-8, GBK 等),然后通过操作系统将字节写入文件。

核心特点:

  • 字符流:它操作的是 char 类型的数据,而不是 byte,这使得处理文本文件更加方便。
  • 便捷性:它简化了文件写入的流程,你不需要像使用 FileOutputStream 那样手动进行字符编码转换。
  • 覆盖 vs 追加:创建 FileWriter 实例时,可以选择是覆盖文件原有内容,还是在文件末尾追加内容。
  • 自动刷新:默认情况下,数据是先写入缓冲区的,需要调用 flush() 方法或关闭流时才会真正写入文件。

如何使用 FileWriter (基本用法)

使用 FileWriter 的标准步骤如下:

  1. 创建 FileWriter 对象:指定要写入的文件路径,如果文件不存在,它会自动创建;如果文件已存在,根据构造函数参数决定是覆盖还是追加。
  2. 写入数据:调用 write() 方法写入字符、字符串或字符数组。
  3. 刷新缓冲区 (可选):调用 flush() 方法,确保所有缓冲区的数据都被写入文件。
  4. 关闭流:调用 close() 方法。这一步至关重要,它会释放系统资源,并确保所有数据都被刷新到文件中,推荐使用 try-with-resources 语句来自动关闭流。

构造函数详解

FileWriter 提供了几个构造函数,以适应不同的需求:

Java FileWriter如何正确使用与关闭?-图2
(图片来源网络,侵删)
构造函数 描述
FileWriter(String fileName) 创建一个 FileWriter,使用给定的文件名,如果文件已存在,将被覆盖
FileWriter(String fileName, boolean append) 创建一个 FileWriterappend 参数为 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:追加模式

如果希望在文件现有内容的基础上添加新内容,应该使用追加模式。

Java FileWriter如何正确使用与关闭?-图3
(图片来源网络,侵删)
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 的局限性与最佳实践

局限性:

  1. 性能问题FileWriter 本身不带缓冲区,每次调用 write() 方法都可能直接进行磁盘 I/O 操作,这非常低效。
  2. 编码问题 (Java 11前):容易因平台默认编码不一致导致乱码。

最佳实践:

  1. 使用 BufferedWriter 包装 FileWriter 为了提高性能,强烈建议FileWriterBufferedWriter 包装起来。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();
            }
        }
    }
  2. 始终使用 try-with-resources FileWriterBufferedWriter 都实现了 AutoCloseable 接口,使用 try-with-resources 语句可以确保无论是否发生异常,流都会被正确关闭,避免资源泄漏。

  3. (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 包装)。

分享:
扫描分享到社交APP
上一篇
下一篇