深入学习Java字符流的使用方法,掌握Reader和Writer类及其子类的特点和应用场景
字符流是Java I/O系统中专门用于处理字符数据的流。与字节流不同,字符流以字符为单位进行读写操作,能够自动处理字符编码转换,特别适合处理文本文件和字符串数据。
| 特性 | 字符流 | 字节流 |
|---|---|---|
| 处理单位 | 字符(char) | 字节(byte) |
| 适用场景 | 文本文件 | 所有文件类型 |
| 编码处理 | 自动处理 | 需要手动处理 |
| 中文支持 | 原生支持 | 需要编码转换 |
| 性能 | 文本处理更高效 | 二进制数据更高效 |
import java.io.*;
public class FileReaderExample {
public static void main(String[] args) {
// 使用try-with-resources自动关闭流
try (FileReader reader = new FileReader("test.txt")) {
int character;
System.out.print("文件内容: ");
// 逐个字符读取
while ((character = reader.read()) != -1) {
System.out.print((char) character);
}
System.out.println();
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {
System.out.println("读取文件时发生错误: " + e.getMessage());
}
}
}
import java.io.*;
public class FileWriterExample {
public static void main(String[] args) {
try (FileWriter writer = new FileWriter("output.txt")) {
String content = "Hello, 这是字符流写入的内容!\n";
content += "支持中文字符的写入。\n";
content += "FileWriter会自动处理字符编码。";
writer.write(content);
System.out.println("内容已成功写入到 output.txt 文件");
} catch (IOException e) {
System.out.println("写入文件时发生错误: " + e.getMessage());
}
}
}
缓冲字符流通过内置缓冲区减少系统调用次数,显著提高I/O性能。BufferedReader还提供了readLine()方法,可以方便地按行读取文件内容。
import java.io.*;
public class BufferedReaderExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("poem.txt"))) {
String line;
int lineNumber = 1;
System.out.println("逐行读取文件内容:");
while ((line = reader.readLine()) != null) {
System.out.println(lineNumber + ": " + line);
lineNumber++;
}
} catch (IOException e) {
System.out.println("读取文件时发生错误: " + e.getMessage());
}
}
}
import java.io.*;
public class BufferedWriterExample {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("log.txt"))) {
// 写入多行日志
writer.write("[INFO] 应用程序启动");
writer.newLine(); // 写入换行符
writer.write("[DEBUG] 初始化配置文件");
writer.newLine();
writer.write("[INFO] 数据库连接成功");
writer.newLine();
// 强制刷新缓冲区
writer.flush();
System.out.println("日志已写入到 log.txt 文件");
} catch (IOException e) {
System.out.println("写入文件时发生错误: " + e.getMessage());
}
}
}
在处理包含中文或其他非ASCII字符的文件时,正确处理字符编码至关重要。使用InputStreamReader和OutputStreamWriter可以明确指定字符编码,避免乱码问题。
import java.io.*;
import java.nio.charset.StandardCharsets;
public class EncodingReaderExample {
public static void main(String[] args) {
try {
// 使用UTF-8编码读取文件
FileInputStream fis = new FileInputStream("chinese.txt");
InputStreamReader reader = new InputStreamReader(fis, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(reader);
String line;
System.out.println("使用UTF-8编码读取中文文件:");
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
bufferedReader.close();
} catch (IOException e) {
System.out.println("读取文件时发生错误: " + e.getMessage());
}
}
}
import java.io.*;
import java.nio.charset.StandardCharsets;
public class EncodingWriterExample {
public static void main(String[] args) {
try {
// 使用UTF-8编码写入文件
FileOutputStream fos = new FileOutputStream("output_utf8.txt");
OutputStreamWriter writer = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write("这是使用UTF-8编码写入的中文内容。\n");
bufferedWriter.write("支持各种Unicode字符: 😀 🎉 ⭐\n");
bufferedWriter.write("English text is also supported.\n");
bufferedWriter.write("日本語も大丈夫です。\n");
bufferedWriter.close();
System.out.println("内容已使用UTF-8编码写入到 output_utf8.txt");
} catch (IOException e) {
System.out.println("写入文件时发生错误: " + e.getMessage());
}
}
}
PrintWriter提供了类似System.out的打印方法,包括print、println和printf,使得文件输出更加便捷。它还具有自动刷新功能和简化的异常处理。
import java.io.*;
public class PrintWriterExample {
public static void main(String[] args) {
try (PrintWriter writer = new PrintWriter(new FileWriter("report.txt"))) {
// 使用print方法
writer.print("学生姓名: ");
writer.print("张三");
writer.println(); // 换行
// 使用println方法
writer.println("学号: 2024001");
writer.println("年龄: 20");
// 使用printf格式化输出
writer.printf("成绩: %.2f分\n", 95.5);
writer.printf("排名: 第%d名\n", 1);
// 表格格式输出
writer.println("\n商品销售报表");
writer.println("===================");
writer.printf("%-10s %-8s %-8s %-10s\n",
"商品名称", "单价", "数量", "总金额");
writer.println("------------------------------------------");
writer.printf("%-10s %8.2f %8d %10.2f\n",
"苹果", 5.5, 10, 55.0);
writer.printf("%-10s %8.2f %8d %10.2f\n",
"香蕉", 3.2, 15, 48.0);
System.out.println("报告已写入到 report.txt 文件");
} catch (IOException e) {
System.out.println("写入文件时发生错误: " + e.getMessage());
}
}
}
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 字符流综合应用示例
* 演示各种字符流的使用方法和最佳实践
*/
public class CharacterStreamDemo {
public static void main(String[] args) {
// 创建测试文件
createTestFile();
// 演示各种字符流操作
demonstrateFileReader();
demonstrateBufferedReader();
demonstrateEncodingHandling();
demonstratePrintWriter();
}
/**
* 创建测试文件
*/
private static void createTestFile() {
try (PrintWriter writer = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream("test.txt"),
StandardCharsets.UTF_8))) {
writer.println("Java字符流学习");
writer.println("这是一个测试文件");
writer.println("包含中文字符: 你好世界!");
writer.println("Unicode字符: 😊 🌟 ⚡");
System.out.println("测试文件创建完成");
} catch (IOException e) {
System.out.println("创建测试文件失败: " + e.getMessage());
}
}
/**
* 演示FileReader基本用法
*/
private static void demonstrateFileReader() {
System.out.println("\n=== FileReader示例 ===");
try (FileReader reader = new FileReader("test.txt")) {
char[] buffer = new char[1024];
int charsRead = reader.read(buffer);
if (charsRead > 0) {
String content = new String(buffer, 0, charsRead);
System.out.println("读取内容:\n" + content);
}
} catch (IOException e) {
System.out.println("读取失败: " + e.getMessage());
}
}
/**
* 演示BufferedReader按行读取
*/
private static void demonstrateBufferedReader() {
System.out.println("\n=== BufferedReader示例 ===");
try (BufferedReader reader = new BufferedReader(
new FileReader("test.txt"))) {
String line;
int lineNumber = 1;
while ((line = reader.readLine()) != null) {
System.out.println("第" + lineNumber + "行: " + line);
lineNumber++;
}
} catch (IOException e) {
System.out.println("读取失败: " + e.getMessage());
}
}
/**
* 演示字符编码处理
*/
private static void demonstrateEncodingHandling() {
System.out.println("\n=== 字符编码处理示例 ===");
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream("test.txt"),
StandardCharsets.UTF_8))) {
String line;
System.out.println("使用UTF-8编码读取:");
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("读取失败: " + e.getMessage());
}
}
/**
* 演示PrintWriter格式化输出
*/
private static void demonstratePrintWriter() {
System.out.println("\n=== PrintWriter示例 ===");
try (PrintWriter writer = new PrintWriter(
new FileWriter("output.txt"))) {
writer.println("字符流学习总结");
writer.println("=================");
writer.printf("学习时间: %s\n", "2024-01-05");
writer.printf("完成度: %.1f%%\n", 100.0);
writer.println("\n主要收获:");
writer.println("1. 掌握了字符流的基本概念");
writer.println("2. 学会了处理字符编码");
writer.println("3. 了解了缓冲流的优势");
System.out.println("学习总结已写入 output.txt");
} catch (IOException e) {
System.out.println("写入失败: " + e.getMessage());
}
}
}
// 1. 使用try-with-resources自动关闭流
try (FileReader reader = new FileReader("file.txt")) {
// 读取操作
} // 自动关闭
// 2. 大文件使用缓冲流
try (BufferedReader reader =
new BufferedReader(new FileReader("large.txt"))) {
// 高效读取
}
// 3. 明确指定字符编码
try (InputStreamReader reader =
new InputStreamReader(
new FileInputStream("file.txt"),
StandardCharsets.UTF_8)) {
// 明确编码
}
// 4. 及时刷新缓冲区
writer.write("重要数据");
writer.flush(); // 确保写入
// 1. 忘记关闭流
FileReader reader = new FileReader("file.txt");
// ... 使用reader
// 忘记关闭,可能导致资源泄露
// 2. 不处理编码问题
FileReader reader = new FileReader("chinese.txt");
// 可能出现乱码
// 3. 频繁小量写入不使用缓冲
FileWriter writer = new FileWriter("output.txt");
for (int i = 0; i < 10000; i++) {
writer.write("line " + i + "\n");
// 性能较差
}
A: 处理文本文件时使用字符流,处理图片、音频、视频等二进制文件时使用字节流。字符流能自动处理字符编码,更适合文本操作。
A: 使用InputStreamReader/OutputStreamWriter并明确指定UTF-8编码,或者确保文件编码与读取编码一致。
A: 默认8192个字符,可以通过构造函数指定大小。合理的缓冲区大小能显著提高I/O性能。