0 前言
字符编码,本质是二进制数据与语言文字的一一对应关系
1 ASCII 编码
-
一个字节有8位,最多可以表示28 = 256种信息。把一个字节最高位固定为
0
,则可以表示128个字符,其中33个控制字符,95个可显字符,这就是ASCII编码。 -
在 ASCII 基础之上,国际标准化组织(ISO)及国际电工委员会(IEC)联合制定的一系列8位元字符集的标准,叫 ISO 8859,全称ISO/IEC 8859,ISO 8859 字符编码方案除了ASCII编码,还使用
0xA0
到0xFF
(十进制为160
~255)
,分别代表 中欧、南欧、北欧等字符集。
2 中文编码
字母文字通常只需要一个字节就能编码,中文、日文、韩文等文字需要不止一个字节。日本把日文编到JIS里,韩国把韩文编到Euc-kr里。
-
1981年国家标准化管理委员会定了一套字符集叫GB2312,每个汉字符号由两个字节组成,理论上它可以表示65536个字符,不过它只收录了7445个字符,6763个汉字和682个其他字符,同时它能够兼容 ASCII,ASCII 中定义的字符只占用一个字节的空间。
-
GB2312 所收录的汉字已经覆盖中国大陆99.75%的使用频率,但是对一些罕见的字和繁体字还有很多少数民族使用的字符都没法处理,于是后来就在 GB2312 的基础上创建了一种叫 GBK 的字符编码,GBK 不仅收录了27484 个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。GBK 是利用了 GB2312 中未被使用的编码空间上进行扩充,所以它能完全兼容 GB2312和 ASCII。
-
GB 18030 是现时最新的字符集,兼容 GB 2312-1980 和 GBK, 共收录汉字70244个,采用多字节编码,每个字符可以有1、2、4个字节组成,某种意义上它能容纳161 万个字符,包含繁体汉字以及日韩汉字,单字节与ASCII兼容,双字节与GBK标准兼容。
3 Unicode代码值
全世界有上百种语言,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。现代操作系统和大多数编程语言都直接支持Unicode。
-
Unicode 是一种编码表,只规定了每个字符对应到唯一的代码值(code point),代码值从
0x0
~0x10FFFF
共 1114112 个值 。Unicode本身并没有规定如何表达这些值 -
而UTF-8,UTF-16,UTF-32等是存储方式,各自定义了信息传输和储存过程中每个字节的格式
3.1 UTF-8编码
UTF-8编码把Unicode代码值转化为“可变长编码”的。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间
ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
UTF-8 的编码规则
- 对于单字节的字符,字节的第一位设为
0
,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。 - 对于n字节的字符(n > 1),第一个字节的前n位都设为
1
,第n+1位设为0
,后面字节的前两位一律设为10
。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
UTF-8 兼容了 ASCII,在数据传输和存储过程中节省了空间,UTF-8 不需要考虑大小端问题。这两点都是 UTF-16 的劣势。
不过对于中文字符,用 UTF-8 就要用3个字节,而 UTF-16 只需2个字节。而UTF-16 的优点是在计算字符串长度,执行索引操作时速度会很快。
Java 内部使用 UTF-16 编码方案。而 Python3 使用 UTF-8。UTF-8 编码在互联网领域应用更加广泛。
3.2 UTF-16编码
- UTF-16 使用二或四个字节为每个字符编码(定长,一般情况下为2字节),因为对于绝大部分字符只使用2个字节就可以表示了
- 对于汉字而言,大部分汉字采用两个字节编码,少量不常用汉字采用四个字节编码
- 而UTF-16存在大小端的问题, UTF-16BE 和 UTF-16LE,在编码前会放置一个
U+FEFF
或U+FFFE
(UTF-16BE 以FEFF
代表,UTF-16LE 以FFFE
代表)
3.3 UTF-32编码
- UTF-32 使用四个字节为每个字符编码,使得 UTF-32 占用空间通常会是其它编码的二到四倍
- UTF-32 与 UTF-16 一样有大尾序和小尾序之别,编码前会放置
U+0000FEFF
或U+0000FFFE
以区分。
3.4 常用语言中编码类型
语言/平台 | 编码类型 |
---|---|
Java | UTF-16 |
JavaScript | UTF-16 |
C/C++ | UTF-8 |
Python | UTF-8 |
Linux | UTF-32 |
Windows | UTF-16 |