inputstreamreader的核心作用是将字节流按指定编码精准解码为字符流,避免乱码;它分两步:先读原始字节,再按真实编码(如"gbk")转字符,必须显式指定编码名,并常与bufferedreader配合提升效率。

转换流 InputStreamReader 的核心作用,是把原始字节流按你指定的字符编码“重新解释”成字符流,从而避开默认编码带来的乱码风险。
为什么直接用 FileReader 会乱码?
FileReader 是字符流,但它内部默认使用系统或 JVM 的默认编码(比如 Windows 上常是 GBK,IDE 中可能是 UTF-8)去解码文件字节。如果文件实际是 GBK 编码,而 FileReader 按 UTF-8 解,一个中文就可能被拆成两个非法字节序列,显示成或问号。
它不关心文件真实编码,只按“约定俗成”的方式硬解——这正是乱码的根源。
InputStreamReader 怎么解决这个问题?
它不跳过字节层,而是明确分两步:
- 先用 FileInputStream 读取文件原始字节(这步不涉及编码,字节原样拿到)
- 再用 InputStreamReader 把这些字节,按你传入的真实编码(如 "GBK" 或 "UTF-8")转成 Java 字符(char/CharSequence)
相当于你亲手控制了解码开关,而不是交给环境猜。
关键写法:必须显式指定编码名
不要用无参构造:
✘ 错误写法(依赖默认编码,不可靠):new InputStreamReader(new FileInputStream("data.txt"))
要用带编码参数的构造:
✔ 正确写法(明确指定,可复现):new InputStreamReader(new FileInputStream("data.txt"), "GBK")new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8)
编码名必须和文件实际保存时使用的编码完全一致。常见判断方式:用记事本或 VS Code 打开文件,看右下角显示的编码;或用命令行工具如 file -i data.txt(Linux/macOS)查看。
搭配 BufferedReader 提升效率
InputStreamReader 本身只做编码转换,不带缓冲。实际读取时建议套一层 BufferedReader:
- 避免每次 read() 都触发底层 I/O 调用
- 支持按行读取(readLine()),处理文本更自然
- 缓冲区大小可调,但通常用默认即可
示例:
try (BufferedReader br = new BufferedReader(<br>
new InputStreamReader(new FileInputStream("data.txt"), "UTF-8"))) {<br>
String line;<br>
while ((line = br.readLine()) != null) {<br>
System.out.println(line);<br>
}<br>
}











