深⼊理解Emoji(⼀)——字符集,字符集编码
最近在开发中遇到了点Emoji相关的问题,便去了解了⼀下Emoji的编码规则,发现其中涉及了许多字符集与字符集编码的知识点,便趁这个机会做⼀次这⽅⾯的总结梳理。本篇内容主要是对字符集和字符集编码的知识整理。
1. 字符集与字符集编码
我们知道,计算机中的所有信息最终都是以⼆进制的形式存储,所以⼈机交互中其实伴随着⼆进制的转换,将我们输⼊到计算机的字符(信息)转换成计算机能识别的⼆进制数据,或将⼆进制数据输出为我们⼈能识别的字符。那什么是字符呢?在计算机领域,我们把诸如⽂字、标点符号、图形符号、数字等统称为字符。⽽由字符组成的集合则成为字符集,字符集由于包含字符的多少与异同⽽形成了各种不同的字符集。所以,为了让计算机能识别出我们字符集⾥的字符,就需要制定⼀套规则,这套规则,就是字符集编码。我们规定字符编码必须完成如下两件事:
1. 规定⼀个字符集中的字符由多少个字节表⽰。
2. 制定该字符集的字符编码表,即该字符集中每个字符对应的(⼆进制)值。
2. ASCII 码
上个世纪 60 年代,美国制定了⼀套字符编码标准,对英语字符与⼆进制位之间的关系,做了统⼀规定。这被称为 ASCII 码,⼀直沿⽤⾄今。
ASCII(American Standard Code for Information Interchange),是⼀种字符编码标准,它的字符集为英⽂字符集,它规定字符集中的每个字符均由⼀个字节表⽰,指定了字符表编码表,称为 ASCII 码表。它已被国际标准化组织定义为国际标准,称为 ISO646 标准。
ASCII 码⼀共规定了 128 个字符的编码,⽐如空格“SPACE”是 32(⼆进制00100000),⼤写的字母 A是 65(⼆进制01000001)等。这128 个符号(包括32个不能打印出来的控制符号),只占⽤了⼀个字节的后⾯ 7 位,最前⾯的 1 位统⼀规定为 0。这种采⽤⼀个字节来编码128 个字符的 ASCII 码称为标准 ASCII 码或者基础 ASCII 码。
但是,由于标准 ASCII 字符集字符数⽬有限,在实际应⽤中往往⽆法满⾜要求。为此,国际标准化组织⼜制定了 ISO 2022 标准,它规定了在保持与 ISO646 兼容的前提下将 ASCII 字符集扩充为 8 位代码的统⼀⽅法。 ISO 陆续制定了⼀批适⽤于不同地区的扩充 ASCII 字符集,每种扩充 ASCII 字符集分别可以扩充 128 个字符,这些扩充字符的编码均为⾼位为 1 的 8 位代码(即⼗进制数 128~255 ),称为扩展 ASCII 码。
但是需要注意,各种扩展 ASCII 码除了编码为 0~127 的字符外,编码为 128~255 的字符并不相同。
⽐如,130 在法语编码中代表了 é,在希伯来语编码中却代表了字母 Gimel (?),在俄语编码中⼜会代表另⼀个符号。因此,ASCII 码的问题在于尽管所有⼈都在 0 - 127 号字符上达成了⼀致,但对于 128 - 255 号字符上却有很多种不同的解释。与此同时,亚洲语⾔有更多的字符需要被存储,⼀个字节已经不够⽤了。于是,⼈们开始使⽤两个字节来存储字符。各种各样的编码⽅式成了系统开发者的噩梦,因为他们想把软件卖到国外。于是,他们提出了⼀个“内码表”的概念,可以切换到相应语⾔的⼀个内码表,这样才能显⽰相应语⾔的字母。在这种情况下,如果使⽤多语种,那么就需要频繁的在内码表内进⾏切换。
3. Unicode
所以,⼈们最终意识到需要⼀种标准的规范来展⽰世界上的所有字符,于是,Unicode就应运⽽⽣了。Unicode最初代表着⼀个字符集,后来慢慢演化成为⼴义的⼀个标准,定义了⼀个字符集以及⼀系列的编码规则,即 Unicode 字符集和 UTF-8、UTF-16、UTF-32 等等编码…
3.1 码点
⼀个字符集⼀般可以⽤⼀张或多张由多个⾏和多个列所构成的⼆维表来表⽰。
⼆维表中⾏与列相交的点,称之为码点(Code Point代码点),也称之为码位(Code position代码位);每
个码点分配⼀个唯⼀的编号,称之为码点值或码点编号,除开某些特殊区域(⽐如代理区、专⽤区)的⾮字符码点和保留码点,每个码点唯⼀对应于⼀个字符。通俗的说,码点就是字符在Unicode中所对应的⼆进制数。
码点值最初⽤两个字节的⼗六进制数字表⽰,⽐如字母A的Unicode码点值为0041,常写作U+0041,这种形式称为Unicode码点名称。后来随着Unicode字符集的不断增补扩⼤(⽐如现在的Unicode字符集⾄少需要21位才能全部表⽰),码点值也扩展为⽤三个字节或以上的⼗六进制数字表⽰。
3.2 码元
在计算机存储和⽹络传输时,码点被映射到⼀个或多个码元(Code Unit)。码元可理解为字符编码⽅式CEF(Character Encoding Form)对码点值进⾏编码处理时作为⼀个整体来看待的最⼩基本单元(基本单位)。
3.3 平⾯
Unicode的编码空间从U+0000到+10FFFF,共有1,112,064个码点,可⽤来映射字符. 整个编码空间可以划分为17个平⾯(plane),每个平⾯16
包含2(65,536)个码位。17个平⾯的码位可表⽰为从U+xx0000到U+xxFFFF,其中xx表⽰⼗六进制
值从00到10,共计17个平⾯。第⼀个平⾯称为基本多语⾔平⾯(Basic Multilingual Plane, BMP),或称第零平⾯(Plane 0)。其他平⾯称为辅助平⾯(Supplementary Planes)。基本多语⾔平⾯内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符,称为代理码点(Surrogate Code Point)。UTF-16就利⽤保留下来的0xD800-0xDFFF区段的码位来对辅助平⾯的字符的码位进⾏编码。除代理码点之外的称为Unicode标量值(Scalar Value)
3.4 编码⽅式
⼀个字符的Unicode码点是确定的。但是在实际传输过程中,由于不同系统平台的设计不⼀定⼀致,以及出于节省空间的⽬的,对Unicode的编码⽅式有所不同。
Unicode的编码⽅式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)。以汉字“汉”为例,它的 Unicode 码点是0x6c49,对应的⼆进制数是 110110*********,⼆进制数有 15 位,这也就说明了它⾄少需要 2 个字节来表⽰。可以想象,在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚⾄更多字节来表⽰了。这就导致了⼀些问题,计算机怎么知道你这个 2 个字节表⽰的是⼀个字符,⽽不是分别表⽰两个字符呢?这⾥我们可能会想到,那就取个最⼤的,假如 Unicode 中最⼤的字符⽤ 4 字节就可以表⽰了,那么我们就将所有的字符都⽤ 4 个字节来表⽰,不够的就往前⾯补 0。这样确实可以解决编码问题,但是却造成了空间的极⼤浪费,如果是⼀个英⽂⽂档,
那⽂件⼤⼩就⼤出了 3 倍,这显然是⽆法接受的。于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前⽐较流⾏的编码⽅式诞⽣了。当然还有⼀个 UTF-32 的编码⽅式,也就是上述那种定长编码,字符统⼀使⽤ 4 个字节,虽然看似⽅便,但是却不如另外两种编码⽅式使⽤⼴泛。
UTF-8
UTF-8(8-bit Unicode Transformation Format)是⼀种针对Unicode的可变长度字符编码,是⽬前互联⽹上使⽤最⼴泛的⼀种 Unicode 编码⽅式,它的最⼤特点就是可变长。它可以使⽤ 1 - 4 个字节表⽰⼀个字符,根据字符的不同变换长度。编码规则如下:
1. 对于单个字节的字符,第⼀位设为 0,后⾯的 7 位对应这个字符的 Unicode 码点。因此,对于英⽂中的 0 - 127 号字符,与 ASCII 码完
全相同。这意味着 ASCII 码那个年代的⽂档⽤ UTF-8 编码打开完全没有问题。
2. 对于需要使⽤ N 个字节来表⽰的字符(N > 1),第⼀个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设
位 10,剩下的⼆进制位则使⽤这个字符的 Unicode 码点来填充。
Unicode⼗六进制码点范围UTF-8 ⼆进制
0000 0000 - 0000 007F0xxxxxxx
0000 0080 - 0000 07FF110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
unicode码和ascii码区别0001 0000 - 0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
以上⾯的“汉”为例,通过上⾯的对照表可以发现,0x0000 6c49位于第三⾏的范围,那么得出其格式为 1110xxxx 10xxxxxx 10xxxxxx。接着,从“汉”的⼆进制数最后⼀位开始,从后向前依次填充对应格式中的 x,多出的 x ⽤ 0 补上。这样,就得到了“汉”的 UTF-8 编码为11100110 10110001 10001001,转换成⼗六进制就是 0xE6 0xB7 0x89。
解码的过程也⼗分简单:如果⼀个字节的第⼀位是 0 ,则说明这个字节对应⼀个字符;如果⼀个字节的第⼀位1,那么连续有多少个 1,就表⽰该字符占⽤多少个字节。当中间出现不符合规则的字节编码,⽐如11100110 10110001 00011101,则系统会判定前⾯的 11100110
UTF-16编码举例

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。