2.1 编码的本质
在开始讲解具体的编码标准之前,我们需要先理解编码到底是什么,以及为什么我们需要字符编码。
信息的数字化表示
计算机的本质是一个电子设备,它只能理解和处理二进制数据(0和1)。而我们人类在日常交流中使用的是各种自然语言的字符(中文、英文、日文等)、符号、数字等信息。要让计算机能够处理这些人类可理解的信息,就需要建立一个从人类字符到二进制数字的映射关系,这个映射过程就是编码。
换句话说:
编码就是将信息从一种格式转换为另一种格式的规则集合。
对于字符编码来说:
- 编码(Encode):将人类可理解的字符转换为计算机可处理的二进制字节序列
- 解码(Decode):将二进制字节序列转换回人类可理解的字符
字符 'A' → 编码 → 二进制 01000001 → 解码 → 字符 'A'
如果编码和解码使用的规则不一致,就会出现我们常说的乱码问题。
字符编码的核心三要素
一个完整的字符编码标准通常包含三个核心要素:
1. 字符集(Charset)
规定了这个编码标准支持哪些字符,每个字符对应一个唯一的编号(码位,Code Point)。
- 例如:ASCII字符集包含了英文字母、数字、常用符号共128个字符
- 例如:Unicode字符集包含了几乎所有人类语言的字符,超过14万个码位
2. 编码方式(Encoding)
规定了如何将字符的码位转换为实际的二进制字节序列。
- 同一个字符集可以有多种不同的编码方式
- 例如:Unicode字符集有UTF-8、UTF-16、UTF-32等多种编码方式
3. 字节序(Endianness)
对于多字节编码,需要规定字节的排列顺序(大端序/小端序)。
- 大端序(Big Endian):高位字节在前,低位字节在后
- 小端序(Little Endian):低位字节在前,高位字节在后
编码发展的历史背景
字符编码的发展历史其实就是计算机全球化的历史:
1. 计算机早期:只支持英文
计算机最早是在美国发明的,早期只需要处理英文字符,所以最早的编码标准ASCII(美国信息交换标准代码)只包含了128个字符,完全可以满足英文处理的需求。
2. 全球化初期:各国自己的编码标准
随着计算机在全球普及,各个国家都需要处理自己的语言文字,于是各个国家都制定了自己的编码标准:
- 欧洲:ISO-8859系列编码,支持欧洲各国语言
- 中国:GB2312、GBK、GB18030等编码,支持中文
- 日本:Shift_JIS编码,支持日文
- 韩国:EUC-KR编码,支持韩文
这一时期的问题是:不同国家的编码标准互不兼容,同一个二进制数值在不同的编码标准中代表不同的字符,跨语言处理非常容易出现乱码。
3. 全球化时代:统一编码标准
随着互联网的发展,不同国家和地区之间的信息交流越来越频繁,编码不兼容的问题越来越突出。于是国际组织制定了Unicode统一字符集,目标是包含全世界所有语言的字符,从根本上解决编码不兼容的问题。
现在Unicode已经成为了全球通用的编码标准,UTF-8是目前使用最广泛的Unicode实现方式。
为什么程序员必须理解编码
很多程序员觉得编码是个很底层的东西,平时开发用框架和库都帮我们处理好了,不需要理解。但实际上编码问题无处不在:
- 文本文件读写:打开文件时如果编码不对,就会出现乱码
- 网络请求:前后端交互时如果编码不一致,就会出现乱码
- 数据库存储:数据库编码和应用编码不一致,存储的内容就会乱码
- 字符串处理:不同语言的字符串实现不同,处理多字节字符时很容易出问题
- 日志分析:日志文件编码不对,分析时就会遇到各种问题
理解编码的本质,能够让你在遇到乱码问题时快速定位原因,而不是靠猜和试错来解决问题。
思考问题
- 你遇到过最印象深刻的乱码问题是什么?当时是怎么解决的?
- 为什么需要有编码和解码两个过程?直接用字符的码位作为存储格式不行吗?
- 你觉得Unicode统一编码标准有什么好处?有什么弊端?