一、Unicode是什么
Unicode(统一码/万国码)是一套字符编码标准,目标是为世界上所有语言的每一个字符分配一个唯一的数字编号,从而解决不同编码系统之间互不兼容的问题;
为什么要给每个字符分配一个唯一数字编号呢
计算机本质上只处理数字,而人类使用的是文字、符号和表情。Unicode 的作用就是建立一套"人类字符 ↔ 计算机数字"的统一对应关系。
在Unicode出现之前,各国都有自己的编码方式,比如:
| 编码 | 各国字符 |
|---|---|
| ASCII | 英文字符 |
| GBK | 中文字符 |
| Shift_JIS | 日文 |
不同编码之间不兼容,同一个数字,在不同的编码中,表示的含义并不相同,就可能导致乱码问题频发,Unicode试图"一统天下"
二、核心概念
1. Character(字符)
人看到的:
😀
叫字符。
2. Code Point(码点)
Unicode 编号:
U+1F600
目前 Unicode 的码点范围是 U+0000 到 U+10FFFF,理论上能容纳超过 100 万个字符。
3. Encoding(编码)
转换:
U+1F600
|
↓
UTF-8
F0 9F 98 80
4. Code Unit(编码单元)
某种编码的基本单位。
例如:
UTF-8,UTF-8 最聪明的地方在于它的可变长度设计(占用 1 到 4 个字节)
英文字符/数字:只占 1 个字节(8 位)。
欧洲文字:通常占 2 个字节。
中/日/韩文:通常占 3 个字节。
罕见字与 Emoji:占 4 个字节。
UTF-8既然是可变长的,那系统是怎么知道一个字符占用了哪几个字节,在什么地方结束的呢?
答:系统之所以能准确识别"这个字符从哪里开始、占用几个字节、到哪里结束",关键在于 UTF-8 设计了一套非常巧妙的前缀自标记规则。
简单来说,字节开头的"前几位(bit)"就是指示灯,告诉系统当前字节是单字节字符、多字节字符的开头,还是随后的接应字节。
Unicode 本身只是一张"字符→编号"的映射表 ,它不规定这些编号在计算机里如何用字节存储。真正决定"如何存成字节"的,是具体的编码方式,常见的有 UTF-8、UTF-16、UTF-32。
三、常见编码方式对比
| 编码 | 每个字符占用字节数 | 特点 |
|---|---|---|
| UTF-8 | 1~4 字节(可变长) | 兼容 ASCII,英文占1字节,中文通常占3字节;互联网、大多数系统的主流选择 |
| UTF-16 | 常用字符占2字节,辅助平面字符占 4字节 | Windows、Java、JavaScript 内部常用 |
| UTF-32 | 固定4字节 | 简单但浪费空间,较少使用 |
四、为什么会有乱码?
乱码本质上是编码和解码方式不一致导致的。比如:
- 一个文件用 UTF-8 编码保存
- 但打开时用 GBK 方式去解码
这样字节序列被错误地"翻译"成了别的字符,就出现了乱码(如常见的"锟斤拷"现象)。
五、几个常见误解总结
❌ Unicode 是一种编码
不准确。
正确:
Unicode 是字符集合和编号标准。
❌ UTF-8 可以表示的字符比 Unicode 多
错误。
正确:
UTF-8 是 Unicode 的一种编码实现。
❌ 一个字符一定占两个字节
错误。
例如 UTF-8:
A
1字节
中
3字节
😀
4字节
六、GBK与UTF-8的关系
简单来说,GBK 和 UTF-8 是两种不同的字符编码方式 。它们最核心的区别在于:GBK 是中国国家标准局制定的区域性编码,专门用来解决中文显示;而 UTF-8 是国际通用的 Unicode 编码实现方式,旨在统全世界所有的语言。
它们之间既有各自的适用场景,也经常在日常使用中因为"互不兼容"而导致乱码。
核心区别对比
| 维度 | GBK 编码 | UTF-8 编码 |
|---|---|---|
| 支持语言 | 主要支持中文(简体/繁体)、英文字符 | 全球所有语言(汉字、韩文、日文、阿拉伯文、Emoji 等) |
| 字符集基础 | 基于中国国家标准 GB2312 扩展 | 基于国际 Unicode 标准 |
| 存储长度 | 英文字符 1 字节,中文字符 2 字节 | 英文字符 1 字节,常用中文字符 3 字节 |
| 兼容性 | 仅在国内或老旧 Windows 系统广泛使用 | 全球互联网标准,跨平台、跨语言兼容性极佳 |
| 应用场景 | 旧版 Windows 软件、部分国内老旧数据库 | 网页开发、Linux 操作系统、现代 API、软件接口 |
它们之间的关键关系
1. 兼容 ASCII,但互相不兼容
- 兼容 ASCII :无论在 GBK 还是 UTF-8 中,基础的英文和数字(如字母
A、数字1)都只占 1 个字节,且两者二进制值完全一致。 - 中文互相不不兼容 :同一个汉字(比如"中"),在 GBK 中占用 2 个字节 ,而在 UTF-8 中占用 3 个字节 。由于它们的二进制映射映射表完全不重合,因此如果用 GBK 方式打开 UTF-8 保存的中文文本,就会产生乱码(常见的比如"锟斤拷"或各种奇怪符号)。
2. Unicode 是它们转换的"桥梁"
GBK 和 UTF-8 不能直接进行简单的数学转换 。如果你要把一个 GBK 编码的文件转成 UTF-8,必须借助 Unicode(万国码):
GBK 字节→查找 GBK 映射表Unicode 码点→应用 UTF-8 编码规则UTF-8 字节\text{GBK 字节} \xrightarrow{\text{查找 GBK 映射表}} \text{Unicode 码点} \xrightarrow{\text{应用 UTF-8 编码规则}} \text{UTF-8 字节}GBK 字节查找 GBK 映射表 Unicode 码点应用 UTF-8 编码规则 UTF-8 字节
也就是说,Unicode 相当于"世界语",任何本土编码(GBK、Big5、Shift-JIS 等)都需要先翻译成 Unicode,才能转写为 UTF-8。
为什么存储中文时长度不同?
- GBK 更节省空间(针对纯中文) :因为 GBK 只需要服务中文和英文,采用双字节定长编码中文,因此一个包含 1000 个汉字的文件在 GBK 下大约占用 2 KB。
- UTF-8 扩展性更好(但中文略变大) :为了兼容全世界数十万种字符,UTF-8 对汉字采用了 3 字节(部分偏僻字 4 字节)的变长编码。同样 1000 个汉字在 UTF-8 下大约占用 3 KB。
提示 :虽然 UTF-8 存中文比 GBK 多消耗 50% 的空间,但现代硬件对这几 KB 的体积并不敏感,跨平台无乱码的通用性远比节省这一点空间重要得多。
实际开发与使用建议
- 新建项目一律优先选择 UTF-8:不论是写代码、建数据库、做网页还是保存 txt 文件,统一使用 UTF-8 可以规避 99% 的乱码问题。
- 遇到乱码怎么排查 :当你在 Windows 控制台或 Python 读写文件发现中文变乱码时,通常是因为源文件的保存格式 与当前软件/终端的默认读取格式不一致(例如文件是 UTF-8,但终端以 GBK 打开)。
Unicode 是给世界所有字符分配唯一编号的标准;UTF-8、UTF-16、UTF-32 是把这些编号转换成计算机字节的不同方法。程序内部通常处理 Unicode,存储和通信时选择某种 UTF 编码。
