初学者应抓住方向、数据类型、编码三点:源→输入流,目标→输出流;文本用字符流并指定UTF-8编码,非文本用字节流;避免FileReader/FileWriter以防乱码。

初学者常卡在“字节流和字符流怎么选”“为什么一读中文就乱码”“控制台能打印,文件却写不对”这类问题上。核心不是记类名,而是抓住三点:方向、数据类型、编码。下面直接说清楚怎么在控制台和文件之间安全转换。
先分清方向:源是哪,目标是哪
所有IO操作都围绕“从哪来、到哪去”展开:
- 源是文件 → 用输入流(InputStream 或 Reader)
- 源是键盘/控制台输入 → 也用输入流(System.in 是 InputStream)
- 目标是文件 → 用输出流(OutputStream 或 Writer)
- 目标是控制台打印 → 用输出流(System.out 是 PrintStream,本质是 OutputStream)
再看数据:纯文本就用字符流,否则用字节流
判断标准很简单:用 Windows 记事本打开文件,能正常看到中文、标点、换行,就是纯文本;如果全是方块、问号或看不懂的符号,大概率是图片、PDF、音频等二进制文件。
- 处理文本(如 .txt、.csv、.log、Java 源码)→ 优先用字符流(Reader/Writer)
- 处理非文本(如 .jpg、.mp3、.zip)→ 必须用字节流(InputStream/OutputStream)
- 键盘输入和控制台输出默认是文本 → 用字符流更自然,但需注意 System.in 是字节流,必须包装
关键一步:字符流必须指定编码,别依赖默认值
字符流背后是解码(读)和编码(写),而编码规则必须明确指定。JVM 默认字符集因系统而异(Windows 常是 GBK,Mac/Linux 常是 UTF-8),不写编码等于埋雷。
- 读文件时:new InputStreamReader(new FileInputStream("a.txt"), "UTF-8")
- 写文件时:new OutputStreamWriter(new FileOutputStream("b.txt"), "UTF-8")
- 不要用 FileReader/FileWriter —— 它们内部调用 Charset.defaultCharset(),极易乱码
- 推荐用 StandardCharsets.UTF_8 替代字符串 "UTF-8",类型安全且无拼写风险
典型场景代码示例
场景1:读文件 → 打印到控制台(文本)
try (InputStream fis = new FileInputStream("data.txt");
Reader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
场景2:键盘输入 → 写入文件(文本)
try (InputStream sysIn = System.in;
Reader isr = new InputStreamReader(sysIn, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
OutputStream fos = new FileOutputStream("output.txt");
Writer osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(osw)) {
String input = br.readLine();
if (input != null) {
bw.write(input);
bw.newLine();
}
}
场景3:复制图片(非文本)→ 必须用字节流
try (InputStream fis = new FileInputStream("a.jpg");
OutputStream fos = new FileOutputStream("b.jpg")) {
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
}
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











