前言
在日常开发的过程中,有关 Unicode
、UTF-8
的问题并不常出现,但在阅读技术文章或源码时出现频率就比较高了。笔者最近刚好就在开发时遇到了和 Unicode
相关的问题,发现自己对这方面的基础知识并没有充分掌握。因此将相关知识梳理出来,帮助大家理解清楚 Unicode
和 UTF-8
。
字符集
什么是字符集?
字符集(Character set)是多个字符的集合,并且每个字符都拥有唯一的编号(即码点,Code Point)。不同的字符集所包含的字符个数不同,常见的字符集有:ASCII
字符集、GB2312
字符集、BIG5
字符集、 GB18030
字符集、Unicode
字符集等。
在没有计算机之前,大部分信息以文本的形式存在,那么如何将文本存储到计算机中呢?
我们知道,在计算机中是通过二进制值来表示信息的,每个二进制位(bit)都有 0
和 1
两种状态。而计算机中存储的最小单位就是字节(Byte),由 8 个二进制位组成,那么就可以表示 2^8=256 种状态。
利用这 256 个二进制值,我们可以将字符转换为数值存储到计算机中,假设我们规定:
A: 00000000
B: 00000001
C: 00000010
这样有了一对一的映射关系后,我们就可以把文本 ABC
用 00000000 00000001 00000010
存储到计算机中。这样的一个包含字符 ABC
的映射集合就是我们自定义的”字符集“。
ASCII码
我们在上一节介绍字符集时自定义了一个只包含 ABC
三个字母的字符集,仅仅作为例子可以,但是应用到实际的话显然是不够用的,因为既没有将所有的字母写入,也无法映射空格或标点符号等字符。
为了解决这个问题,在上世纪六十年代,美国制定了一套字符编码,即 ASCII
码(American Standard Code for Information Interchange,美国信息交换标准代码,详见维基百科-ASCII),将英语字符与二进制值进行一一对应,一直沿用至今。
标准 ASCII
码使用7
位二进制数(剩下的首位二进制为0
)来表示所有的大写和小写字母,数字 0 到 9、标点符号,以及在美式英语中使用的特殊控制字符。比如空格 SPACE
的十进制值是 32(二进制00100000
),大写的字母 A
的十进制值是 65(二进制01000001
),如下图所示。
ASCII
码对于美国这种使用英语作为母语的国家是够用了,但是对于使用其他语言的国家,128 个二进制值仍不足以表示所有字符,于是一些国家决定利用字节中的闲置最高位编入新的字符,这样一来这些国家使用了 8 位二进制值就可以表示最多 256 个字符。
然而这又带来了新的问题,即使不同国家都使用 256 个字符的编码方式,但是同一个二进制值在不同的国家却表示不同的字符,例如 130 在法语中表示 é ,在希伯来语编码中却代表了字母Gimel (ג),就会造成乱码。
为了解决多语言环境下产生的编码冲突问题,Unicode
应运而生。
Unicode
Unicode
将世界上的所有字符囊括其中,并为每一个字符定义唯一的代码(即一个整数),称作码点(