什么是字符集?什么是字符编码?他们之间有什么关系?
软件开发中常见的 ASCII、GB2312、GBK、Unicode、UTF-8 这些大家都听说过,但是很多开发人员依然把字符集和字符编码混为一谈,搞不清概念。所以特别有必要在此梳理一下字符集和字符编码的概念以及他们之间的关系。
字符集
日常使用的数字、字母、文字、标点符号,图形符号等都称作字符。由很多个字符组成的集合叫做字符集
。
可以人为的根据某个规则将一些符号归纳为一组集合,这些文字符号的集合就称为一个字符集。
字符编码
计算机底层使用的是二进制运算,所有的数据也是以二进制进行处理和传输。
为了让计算机能够识别和处理人类的文字、符号、数字等,就需要一个转换规则,把人类的字符转换成计算机认识的二进制,也就是0和1。这个转换规则称为字符编码
。
ASCII
American Standard Code for Information Interchange (美国信息交换标准代码)
ASCII字符集
由于计算机最早由美国人发明,所以只需要让计算机认识英文字符即可,于是美国人就定义了一组叫做ASCII的字符集。
ASCII包含可显示字符(大小写英文字母、阿拉伯数字、西文符号)和控制字符(回车、换行等)。
ASCII字符编码
划分好了字符集后,就需要定制对应的转换规则。
ASCII字符编码规则使用8位表示一个字符,总共有256个字符,下图是ASCII的部分码表。

缺点
ASCII的局限在于只能显示26个基本拉丁字母、阿拉伯数字和英式标点符号。计算机发展至今,仅支持现代美国英语是不够的。世界上还有其他国家的语言字符,所以现代软件一般都使用后面提到的Unicode字符集。
GB2312
GB2312字符集
计算机普及到中国后,为了让计算机能显示中文,我们也必须制定一套字符集。
国家标准总局于1980年发布了中华人民共和国国家标准简体中文字符集
,全称《信息交换用汉字编码字符集·基本集》。GB 2312-80
GB2312字符集标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。
GB2312字符编码
规划了GB2312字符集后,需要制定对应的编码规则以便让计算机能够进行处理和转换,GB2312字符集
对应的字符编码为GB2312字符编码
。
GB2312字符编码兼容了ASCII字符编码的前127个字符,从127个字符之后开始每一个图形字符都采用两个字节表示。在ASCII里本来就有的数字、标点、字母都重新编了两个字节长的编码,这就是常说的“全角”字符,而原来在127号以下的那些字符就叫”半角“字符。以下是GB2312字符编码部分码表。

是不是很像谍战片里发电报的密文?字符编码就像密文对应的密码本,有了字符编码,计算机对应的字符处理程序才能根据对应的字符编码对字符进行处理。
GBK
GB2312的扩展
GBK字符集
由于GB2312字符集只包含了常见的简体汉字,不包含繁体字和一些罕见字,为了支持这些字符,行业推出了GBK字符集标准。
GBK字符集是GB2312字符集的补充,K表示对GB2312的扩展,这个字符集纳入了对繁体汉字和罕见字符的支持。
GBK字符编码
GBK字符编码与GB2312字符编码方式完全相同,只是对GB2312进行了扩展。
GBK是一个行业标准(非国家标准),GBK曾经是由国家技术监督局标准化司公布的“技术规范指导性文件”。
GB18030
信息技术 中文编码字符集 GB18030-2005
GB18030总共有两套标准
GB18030-2000 2000年发布,在GBK基础上增加了CJK统一汉字扩充A的汉字,为GBK的代替版本。现已废止。
GB18030-2005 2005年发布,在GB18030-2000基础上增加了CJK统一汉字扩充B的汉字。现行版本。
GB18030字符集
随着计算机在中国的逐步发展,国家对一些汉字字符集也进行了一些修正,纳入了少数民族的文字符号和一些日韩汉字。
GB18030标准向下与国家标准GB2312信息处理交换码所对应的内码兼容。在字汇上支持GB13000的全部中、日、韩(CJK)统一汉字(包括CJK统一汉字扩充A、CJK统一汉字扩充B)字符和我国部分少数民族文字的字符。
GB18030字符编码
采用单字节、双字节或四字节对字符编码。任何一个字节均由八位二进制位串组成,任何一个八位的值均由0x00至0xFF的十六进制记数法表示。凡数字前标有0x的表示采用十六进制,未标有0x的表示采用十进制。单字节部分采用GB/T11383-1989的编码结构与规则,使用0x00至0x7F码位。双字节部分采用两个八位二进制位串表示一个字符,其首字节码位从0x81至0xFE,尾字节码位分别是0x40至0x7E和0x80至0xFE。四字节部分采用GB/T11383-1989未采用的0x30到0x39作为对双字节编码扩充的后缀。这样扩充的四字节编码,其范围为0x81308130到0xFE39FE39。


单字节部分的码位分配
双字节部分的码位
四字节部分的码位分配收录了汉字和一部分我国少数民族文字
详细的编码规则可查阅国家标准化管理委员会发布的GB18030-2005
Unicode
统一码,编码了世界上大部分的文字系统。
除了中国以外,世界上的其他国家在计算机领域也在同步发展,每个国家都定制了自己的字符集。
随着互联网的发展,计算机之间的信息传输交互由于编码的不同,出现了乱码无法解析等现象。
那么有没有一套收录全世界各个国家名族的所有字符的字符集呢?答案是肯定的。
Unicode字符集
为了全世界的计算机能够统一标准的处理字符,Unicode联盟制定了一套统一的文字编码系统Unicode。
Unicode联盟是统筹Unicode发展的非营利组织,有来自多个国家政府和各大软件商的代表参与。Unicode联盟积极与各标准制订机构合作,包括国际标准化组织(ISO)、国际电工委员会(IEC)、万维网联盟(W3C)、互联网工程工作小组(IETF)和欧洲计算机制造协会(ECMA)等。
Unicode字符集每年都在修订和更新中,持续不断地纳入新的文字和字符。
Unicode字符编码
Unicode编码系统可分为编码方式和实现方式两个层次。
编码方式
Unicode字符编码包含了17个平面,我们常用的英文、文字、标点符号的编码基本覆盖在平面0,这个平面目前使用16位的编码空间,也就是每个字符占用2个字节,但是Unicode字符编码不是必须采用2个字节编码的,最长可以使用4个字节编码,也就是32位,理论上能表示2^32个字符,覆盖一切语言所用的符号。
Unicode编码的缺点
Unicdoe编码的优点是能覆盖世界上任何一种语言符号,但是缺点也很明细,常用的文字字符采用2个字节16位的编码,在进行字符存储和网络传输时消耗的资源是比较多的。
比如一个仅包含7位ASCII字符的Unicode文件,每个字符都用2个字节进行Unicode编码传输,第一个字节的前8位始终为0,就造成了很大的浪费。
实现方式
Unicode的实现方式不同于编码方式。一个字符的Unicode编码确定。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。为了节省存储空间和提高网络传输效率,制定了Unicode转换格式(Unicode Transformation Format),简称为UTF。
UTF-32、UTF-16、UTF-8等都是为了转换Unicode码所制定的各种转换方案的具体实现。
UTF-8
UTF-8编码规则采变长字节进行编码
在ASCII码的范围用一个字节表示,当文件中只有ASCII码时,存储的文件都为一个字节,读写都能和以前的ASCII文件兼容。
文件中如果有大于ASCII码范围的字符,就会由上图所示的,第一字节的前几位表示该unicode字符的长度,比如110xxxxx前三位的二进制表示告诉我们这是个2Byte的Unicode字符;1110xxxx是个三位的Unicode字符,依此类推;xxx的位置由字符编码数的二进制表示的位填入。越靠右的x具有越少的特殊意义。只用最短的那个足够表达一个字符编码数的多字节串。
Unicode字符集规定的标准编码方案是UCS-2(UTF-16),用两个字节表示一个Unicode字符。比如在JVM规范中明确说明了java的char类型使用的编码方案是UTF-16。除此之外Unicode的实现方式还包括UTF-7、Punycode、CESU-8、SCSU、UTF-32等。