Java中用字符流复制文本文件的核心是使用Reader/Writer及其子类,推荐InputStreamReader/OutputStreamWriter显式指定编码(如UTF-8)以避免乱码,并通过char[]缓冲区高效读写,配合try-with-resources确保资源正确关闭。

Java 中用字符流复制文本文件,核心是使用 Reader 和 Writer 及其子类(如 FileReader / FileWriter 或更推荐的 InputStreamReader / OutputStreamWriter),并注意编码一致、资源正确关闭。
用 FileReader + FileWriter 复制(简单但有局限)
适合纯 ASCII 或默认编码环境,不显式指定字符集,依赖系统默认编码(容易乱码):
- 创建
FileReader读源文件,FileWriter写目标文件 - 用循环逐字符或批量读取(推荐用
char[]缓冲区提升效率) - 务必在
finally或 try-with-resources 中关闭流
示例(带缓冲):
try (FileReader fr = new FileReader("src.txt");
FileWriter fw = new FileWriter("dst.txt")) {
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1) {
fw.write(buf, 0, len);
}
}
用 InputStreamReader + OutputStreamWriter 指定编码(推荐)
避免乱码的关键:显式指定字符集(如 UTF-8),尤其源文件非系统默认编码时:
立即学习“Java免费学习笔记(深入)”;
- 用
FileInputStream+InputStreamReader构建带编码的输入字符流 - 用
FileOutputStream+OutputStreamWriter构建带编码的输出字符流 - 同样建议用
char[]缓冲读写
示例(UTF-8 安全复制):
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("src.txt"), "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("dst.txt"), "UTF-8")) {
char[] buf = new char[1024];
int len;
while ((len = isr.read(buf)) != -1) {
osw.write(buf, 0, len);
}
}
用 Files.copy() + 字符流包装(简洁现代方式)
Java 7+ 推荐用 Files 工具类配合 Charset,底层自动处理编码与资源管理:
- 用
Files.lines()读取所有行(返回 Stream),再写入新文件 - 或直接用
Files.copy(InputStream, OutputStream),再用InputStreamReader/OutputStreamWriter包装 - 最简方案:用
Files.copy(Path, Path, CopyOption...)配合字节流,但需确保源目标都是文本且编码已知——严格说这不属于“字符流”,所以若题目明确要求字符流,此法需搭配转换
真正符合“字符流”且简洁的做法(仍基于 Reader/Writer):
Path src = Paths.get("src.txt");
Path dst = Paths.get("dst.txt");
try (BufferedReader br = Files.newBufferedReader(src, StandardCharsets.UTF_8);
BufferedWriter bw = Files.newBufferedWriter(dst, StandardCharsets.UTF_8)) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine(); // 保留换行
}
}
注意事项和常见坑
-
不要混用字节流和字符流直接复制文本:比如用
FileInputStream.read()读字节再转字符串,易因编码不匹配丢数据 -
换行符要手动处理:
readLine()会吃掉换行符,写入时需调用newLine() - 小文件可一次性读取,但大文件必须用缓冲,否则性能极差
-
异常要捕获或抛出:
IOException必须处理,别只打印堆栈就忽略


















