前言
本笔记围绕字节流、字符流、编码转换、中文传输、底层原理展开,全程还原问答逻辑,梳理易混点、核心考点和易错坑,适配Java IO基础复盘与面试备考。
目录
Q1:字节流一次读一个字节,为什么read()能直接读出字符'a'?
Q2:Java的char和文本文档里的字符,字节占用为啥不一样?
Q4:String的toCharArray()和getBytes()有啥区别?
Q5:FileOutputStream(字节流)怎么保证中文字符正确写出?是JVM自动处理吗?一次写几个字节?
[1. 字节流(Byte Stream)](#1. 字节流(Byte Stream))
[2. 字符流(Char Stream)](#2. 字符流(Char Stream))
[3. 编码转换核心逻辑](#3. 编码转换核心逻辑)
[4. 易混点对比](#4. 易混点对比)
一、基础核心问答(直击疑问)
Q1:字节流一次读一个字节,为什么read()能直接读出字符'a'?
A:
-
字节流read()底层永远只读1字节,这是固定规则,不会改变;
-
UTF-8编码下,英文字母、数字、半角符号仅占1字节,读1字节刚好凑成完整字符,看似"一次读全字符";
-
中文UTF-8占3字节,字节流只能分次读,无法直接拼成完整字符,会出现乱码。
Q2:Java的char和文本文档里的字符,字节占用为啥不一样?
A:
-
Java内存char :固定2字节(UTF-16编码),1个char对应1个字符,无论中英文;
-
硬盘文件字符 :UTF-8编码下,英文1字节、中文3字节(节省存储空间);
-
二者标准不冲突,Java会通过编码转换做适配。
Q3:两边字节标准不一致,会不会导致内容解析出错?
A:
-
本身标准不一致,但编码转换器会做自动翻译,正常使用无问题;
-
乱码根源:编码不统一(如文件GBK、读取用UTF-8)、字节拆分不完整(字节流读中文只读部分字节);
-
只要编码一致、字节完整,就能正常还原内容。
Q4:String的toCharArray()和getBytes()有啥区别?
| 方法 | 返回类型 | 数据含义 | 长度规则 | 适用场景 |
|---|---|---|---|---|
| toCharArray() | char[] | Java内存原生字符(2字节/字符) | 等于字符串字符个数 | 操作字符串内容(遍历、修改字符) |
| getBytes(编码) | byte[] | 编码后的硬盘/传输字节 | 等于总字节数(英文少、中文多) | 文件写入、网络传输、IO交互 |
| ⚠️ 避坑:getBytes()必须指定编码(如UTF-8),否则用系统默认编码,极易乱码 |
Q5:FileOutputStream(字节流)怎么保证中文字符正确写出?是JVM自动处理吗?一次写几个字节?
A:
-
字节流不做编码转换,只负责原封不动搬运字节,不识别中文;
-
正确性靠**getBytes(UTF-8)**提前把字符转成完整编码字节数组;
-
底层一次只写1字节,批量写字节数组时,是循环逐个写出;
-
打开不乱码:编辑器用相同编码(UTF-8)解析字节。
Q6:UTF-8怎么区分多字节中文和单字节英文?
A:靠唯一二进制前缀识别(核心规则):
-
0xxxxxxx:单字节(英文/数字),独立成字符;
-
1110xxxx:三字节首字节,后续需跟2个10xxxxxx续字节;
-
10xxxxxx:仅为续字节,不能单独成字符;
-
字节流不识别前缀,仅编辑器/解码工具按此规则拼接字符。
Q7:图片等二进制资源,和文本字节传输有啥不一样?
A:
-
图片/音频/视频无字符、无编码,纯二进制格式数据,每个字节有固定格式含义(文件头、像素、分辨率等);
-
字节流必须一字不差传输,不能做任何编码转换,否则文件损坏;
-
浏览器/图片软件按文件格式解析,不按字符编码解析。
Q8:字节流按byte传输,会不会限制效率?
A:
-
不会限制,反而是最高效的设计;
-
计算机硬件(CPU、内存、网络)最小可寻址单位是1字节,无法按bit操作;
-
上层通过缓冲区批量读写(如8192字节),一次传输大量字节,并非逐个单发;
-
字节流无编码开销,传输速度远快于字符流。
Q9:字节流+编码转换,编码转换是谁做的?
A:
-
字节流只搬运字节,不参与任何编码转换;
-
编码转换由转换流 执行:InputStreamReader(字节→字符)、OutputStreamWriter(字符→字节);
-
字符流(FileReader/FileWriter)底层就是转换流+字节流,自动封装编码逻辑。
Q10:字节流能传中文,为啥还要字符流?
A:
-
字节流高效但不便捷,操作文本需手动转字节、处理编码、拼接字符串,代码繁琐易乱码;
-
字符流是面向人类的便捷封装:自动编码转换、支持直接读写字符串/行、无需操作byte数组;
-
定位:字节流负责底层高效传输,字符流负责文本便捷操作。
二、核心知识点梳理(考点汇总)
1. 字节流(Byte Stream)
-
顶层父类:InputStream(输入)、OutputStream(输出)
-
操作单位:1字节(byte)
-
适用场景:所有文件类型(图片、音频、视频、文本),纯二进制传输
-
特点:万能、高效、无编码开销、不处理字符
-
常用实现:FileInputStream、FileOutputStream、BufferedInputStream
2. 字符流(Char Stream)
-
顶层父类:Reader(输入)、Writer(输出)
-
操作单位:1字符(char)
-
适用场景:纯文本文件(.txt/.java),尤其含中文的文本
-
特点:便捷、自动编码、防乱码、底层依赖字节流
-
常用实现:FileReader、FileWriter、BufferedReader(支持readLine())
3. 编码转换核心逻辑
字符流 = 字节流 + 编码转换器(InputStreamReader/OutputStreamWriter)
-
读流程:文件字节 → 字节流 → 转换流解码(字节→char)→ 字符流
-
写流程:字符 → 字符流 → 转换流编码(char→字节)→ 字节流写出
-
乱码根源:编码不一致、字节不完整、未指定编码
4. 易混点对比
-
字节流:面向机器、底层、万能、高效、操作byte
-
字符流:面向人类、上层封装、文本专用、便捷、操作char/String
-
char(内存2字节)≠ 文件字节(英文1/中文3),靠编码转换适配
三、易错避坑总结
-
禁止用字节流直接读中文并强转字符,会乱码
-
getBytes()/new String()必须显式指定UTF-8编码,拒绝默认编码
-
字节流不识别编码和字符,仅搬运,正确性靠编码前后一致
-
二进制文件(图片/视频)严禁用字符流操作,会损坏文件
-
FileReader/FileWriter无法指定编码,需直接用InputStreamReader/OutputStreamWriter