Unicode、UTF-8、UTF-16 到底是什么关系?
Unicode 是字符集(编号),UTF-8/16 是编码方式(怎么存)。讲清码点、变长存储、为什么中文占 3 字节以及乱码的根源。
一、字符集 vs 编码方式
最核心的一句话:
- Unicode 是字符集:给全世界每个字符分配唯一编号(码点),如「中」= U+4E2D。
- UTF-8/UTF-16/UTF-32 是编码方式:规定码点在内存/磁盘中用几个字节、怎么排。
类比:Unicode 是「学号分配表」,UTF-8 是「学号怎么印在胸牌上」。
二、UTF-8:变长的天才设计
UTF-8 用 1-4 字节存一个码点:
- ASCII(英文、数字、常见符号):1 字节,与老系统完全兼容。
- 拉丁字母扩展、希腊文等:2 字节。
- 中文常用字:3 字节。
- emoji、生僻字:4 字节。
首字节的前导 1 的个数标识长度,解码器自同步,这是互联网选择 UTF-8 的根本原因。
三、UTF-16 与「字节序」
UTF-16 用 2 或 4 字节存码点,Windows API、Java 内部字符串用它。多字节存储引出字节序问题:同样两字节,大端(BOM:FE FF)和小端(FF FE)读法不同——文件开头看到的 BOM 就是干这个的。
「笨」字 UTF-8 是 E7 AC A8,UTF-16 大端是 7B28——同一字符、不同编码、字节完全不同,这就是乱码的本质:用 A 编码写入、用 B 编码读取。
四、实战建议
- 新项目一律 UTF-8(MySQL 记得 utf8mb4,老 utf8 存不了 4 字节 emoji)。
- 排查乱码先问三个问题:文件实际是什么编码、程序按什么编码读、输出端按什么编码显示。
- HTTP 头
Content-Type: text/html; charset=utf-8显式声明,别让浏览器猜。
在线体验
不用装任何环境,直接用本站Base64 编解码工具在线操作,数据都在浏览器本地处理,方便又安全。
常见问题
为什么中文在 UTF-8 里是 3 个字节?
Unicode 把常用汉字分配在 U+4E00-U+9FFF 区间,落在 UTF-8 的 3 字节编码范围(U+0800-U+FFFF)。 emoji 在更大的辅助平面,需要 4 字节。
MySQL 的 utf8 和 utf8mb4 有什么区别?
MySQL 的 utf8 最多只支持 3 字节,存 emoji(4 字节)会报错或丢失;utf8mb4 才是完整 UTF-8。新库建表直接用 utf8mb4。
BOM 是什么?要加吗?
BOM 是文件开头的字节序标记。UTF-8 不需要 BOM(无字节序问题),加了反而可能导致网页头部多出空行或脚本解析异常,Web 场景建议不加。
