【Java】转换流详解
大家好,本篇继续更新 Java IO 流系列内容,前面我们讲解了字节流、字符流,今天重点来讲转换流。在实际开发中,字节流与字符流互转、文件读写乱码等问题,基本都靠转换流来解决。
一、转换流的核心作用
Java IO 分为字节流和字符流两大类:
- 字节流:万能流,可操作所有类型文件,但直接读写文本容易出现编码问题
- 字符流:专门用来读写文本文件,基于字符操作
而转换流就是两者之间的桥梁,主要包含两个核心类:
InputStreamReader:字节输入流 → 字符输入流OutputStreamWriter:字符输出流 → 字节输出流
二、编码、解码与字符集
想要理解转换流,先要搞懂编码、解码和字符集,这也是乱码产生的根源。
1. 编码与解码
简单总结:
- 编码:字符(人能看懂)→ 字节(计算机存储)
- 解码:字节(计算机存储)→ 字符(人能看懂)
文本在计算机中最终都是以二进制字节形式保存,读写时就会经历编码和解码两个过程。
2. 常见字符集
不同字符集对应不同的编码规则,日常开发高频使用:
- ASCII:仅支持英文字母、数字、基础符号
- GBK:国内常用中文编码,兼容 GB2312,汉字占 2 个字节
- UTF-8:互联网主流编码,通用多国语言,汉字占 3 个字节
3. 乱码产生原因
编码和解码使用的字符集不一致,是乱码的唯一核心原因。
举个例子:文件按照 GBK 编码保存,读取时却用 UTF-8 解析,最终就会出现乱码。而转换流最大的价值,就是可以手动指定读写的字符集,从根源解决乱码。
三、InputStreamReader 字节转字符输入流
InputStreamReader 是 Reader 的子类,负责把字节输入流包装为字符输入流,支持自定义字符集。
1. 常用构造方法
InputStreamReader(InputStream in):使用系统默认字符集InputStreamReader(InputStream in, String charsetName):指定字符集(推荐)
2. 代码示例(读取指定编码文件)
下面演示用 InputStreamReader 以 GBK 编码读取本地文本文件:
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
public class InputStreamReaderDemo {
public static void main(String[] args) {
// 1. 创建字节输入流
try (FileInputStream fis = new FileInputStream("test.txt");
// 2. 字节流转为字符流,指定编码为GBK
InputStreamReader isr = new InputStreamReader(fis, "GBK")) {
// 定义字符数组接收数据
char[] chars = new char[1024];
int len;
// 循环读取文本
while ((len = isr.read(chars)) != -1) {
System.out.print(new String(chars, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、OutputStreamWriter 字符转字节输出流
OutputStreamWriter 是 Writer 的子类,负责把字符输出流包装为字节输出流,写入文件时可指定编码。
1. 常用构造方法
OutputStreamWriter(OutputStream out):使用系统默认字符集OutputStreamWriter(OutputStream out, String charsetName):指定字符集(推荐)
2. 代码示例(按指定编码写入文件)
演示以 UTF-8 编码向文件写入文本:
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
public class OutputStreamWriterDemo {
public static void main(String[] args) {
// 1. 创建字节输出流
try (FileOutputStream fos = new FileOutputStream("output.txt");
// 2. 字符流转字节流,指定编码UTF-8
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8")) {
// 写入文本内容
String content = "Java转换流实战,解决中文乱码问题";
osw.write(content);
// 刷新缓冲区,确保数据写入文件
osw.flush();
System.out.println("写入完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
五、综合案例:读写统一字符集,彻底避免乱码
实际开发中,写入和读取必须使用相同字符集。下面写一个完整案例:先用 GBK 写入文件,再用 GBK 读取文件。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
public class ConvertStreamTest {
public static void main(String[] args) {
// 1. 以GBK编码写入文件
try (FileOutputStream fos = new FileOutputStream("gbkFile.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK")) {
osw.write("测试中文内容:Java IO 转换流");
osw.flush();
System.out.println("GBK编码写入成功");
} catch (IOException e) {
e.printStackTrace();
}
// 2. 以GBK编码读取文件
try (FileInputStream fis = new FileInputStream("gbkFile.txt");
InputStreamReader isr = new InputStreamReader(fis, "GBK")) {
char[] buf = new char[1024];
int length = isr.read(buf);
System.out.println("读取内容:" + new String(buf, 0, length));
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行后可以正常展示中文,不会出现乱码;如果把读取编码改为 UTF-8,立刻就会出现乱码,大家可以自行测试对比。
六、总结
- 转换流分为
InputStreamReader和OutputStreamWriter,是字节流与字符流的转换桥梁。 - 文本乱码的本质:编码、解码字符集不统一,转换流的核心作用就是手动指定编码。
- 开发规范:操作文本文件时,尽量主动声明字符集,不要依赖系统默认编码,保证程序跨平台稳定。
- 使用完毕记得关闭流,推荐使用
try-with-resources语法,自动释放资源。
本篇 Java 转换流内容就分享到这里,下一篇我们继续更新 IO 流相关知识点,感兴趣的朋友可以持续关注。



