Unicode字符集与UTF-8编码的关系

以下内容均整理至维基百科,知乎部分答案以及网络。

首先明确两个概念:
(1)字符集:为每个字符分配一个唯一的ID(学名为码位或码点,Code Point);
(2)编码规则:将码点转换为字节序列的规则。(编码或解码)
而Unicode是一套字符集,UTF-8是建立在Unicode字符集之上的一套编码规则。

为何会存在字符集?

        原因很简单,因为计算机中的数据都是二进制表示的,这个时候为了能够让计算机以二进制的形式识别和存储人类语言中所用到的一些符号,那么就需要制定一套规则,让二进制编码能够和现实中的字符一一对应起来。这个时候就出现了第一套字符集规范,ASCII(美国信息交换标准代码),它最初以7位二进制来表示一些西方常用的字符,比如:0x20(0~31)以下表示的是一些控制符,0x20以上到0x7f(32~127)则表示如空格,字母,数字等字符(基本上就是键盘上的所有输入字符)。但是随着计算机的不断普及和发展,已有的字符集已经无法表示一些其他字符,于是在ASCII的基础上又诞生了基于ASCII的扩展字符集(扩展到了255)。

        再后来由于计算机在全世界范围内的普及,现有的字符集已经不可能表示不同文化不同语种中的各色各样的字符。原有的单字节字符集已经完全不够用了。这个时候机智的中国人民就出手了,首先把ASCII扩展字符集中大于0x7f的扩展字符通通砍掉,只保留原有的0x00~0x7f的字符(称之为半角字符)。在此基础上,增加了一个字节,使用两个字节来编码其他的字符,高位字节范围0xA1~0xF7(161~247),低字节范围0XA1~0XFE(161~254),这被称为全角字符。在其中不仅编码了7000个汉字,还顺便把罗马字,日语的假名等都编辑进去。这也就是后来被称为GB2312的字符集,它实际上是对ASCII码的中文扩展。

        但是后来,发现依旧有许多汉字没有被编码进来,而且即使用上GB2312中未使用的码点也完全不够。所以,又在GB2312的基础上,做了进一步的扩展,扩展之后的字符集不仅包括GB2312的内容,又增加了将近20000个新的汉字和符号。这个字符集编码方案被称为GBK标准,即汉字内码编码规范。后来的后来,随着少数民族语言的引入,GBK标准扩展为GB18030。至此,中文扩展字符集的扩展就告一段落了。由于在这套字符集中,一个字节长的英文字符和两个字节长的中文字符都被编码在一起,于是人们称之为双字节字符集(DBCS)。这也正是“一个汉字算两个字符”的由来。

        中国人民的字符编码问题算是暂时解决,但是世界范围内的字符表示则出现了问题。各国各地区人民纷纷推出自己的字符集,这就导致在世界范围内没有一个统一的字符集标准去进行相互的通信。这个时候,国际标准化组织出手了,废弃了所有地区性的编码方案,重新设计了一套包含世界上所有字符的字符集,unicode字符集横空出世,全称Universal Multiple-Octet Coded Character Set,简称UCS。

        unicode字符集初始制定时,直接规定一个字符必须使用2个字节,也就是16位来对字符进行码点的分配。对于那些ASCII字符集(未扩展的),采取的是原有低8位编码不变,高8位以0进行填充的方式。显然这种编码方式虽然“整齐”,但是对于单字节英文字符采用双字节表示,造成了大量的位空间的浪费。而且在对编码的字符进行的传输的过程中,如何解码也成了一个巨大的问题(后来由于字符数量的进一步扩充,unicode编码不再局限于双字节表示字符(基本多语言平面BMP),开始出现三字节(扩展平面)来表示一个字符),因为设备在接收到一个三字节的二进制数据,无法判断这三个字节表示的是一个字符还是两个字符。

        原本unicode字符集被设计出来就是为了能有一个世界范围内数据相互通信编码的统一的标准,但是由于以上两个原因,造成了编码后的字符难以在不同设备中顺利解码。所以unicode字符集在一段时间内难以推广。

UTF的出现以及unicode字符集真正推广

        为了解决unicode字符集的在互联网中的传输解码问题,众多诸如UTF-8,UTF-16的面向传输的UTF标准出现了。UTF-8每次以8bit为单位传输数据,UTF-16每次以16bit为单位传输数据。而UTF-8最大的一个特点就是它是一种变长的编码方式,可以使用1~4个字节来表示一个字符,根据不同的unicode字符集码点的范围,来进行相应的编码(这也是为何说UTF-8是建立在unicode字符集上的一套编码规则),编码规则如下:

U+0000 ~ U+007F : 0XXXXXXX
U+0080 ~ U+07FF : 110XXXXX 10XXXXXX
U+0800 ~ U+07FF : 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+1FFFF : 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX

以上可见UTF-8中,英文字符单字节表示,中文字符则是三个字节表示。并且有了特定的前缀,这样UTF-8编码过后的unicode字符集在传输的过程中,也能够避免歧义的问题。同时,在一定程度上还解决了unicode字符集编码方式中浪费空间的问题。

以上就是本文的全部内容。

发表评论

电子邮件地址不会被公开。 必填项已用*标注