On Unicode

Unicode mentioned, our first reaction must be ---- it is a coding, it is not true, and today we say it in the end is Gesha Unicode

Let me talk about what is Unicode, code point, to get to know some concepts must be clear

What is Unicode?

Unicode character encoding defines almost all of the world (that is, your eyes see characters such as ABC, characters, etc.) digital representation, but also Unicode compatible with older versions of a lot of coding standards, such as the familiar ASCII code.

What is the code point?

Everyone in our country corresponds to a unique ID number, but also to each Unicode character issued an identity card, a string of unique numeric ID identifies the characters on this "identity."

This string of numbers unique in the entire world of computers, Unicode string of digital ID to a name called [code points].

How to code point is represented?

U + XXXXXX is the code point representation, X represents a hexadecimal number, there may be 4-6, less than 4 prior to make up the complement 0 4, is more than a few are several press.

The ASCII characters A, 65 is known, to convert 65 to hexadecimal 41 is, as previously complement rule 0, then A represents the character code point is U + 0041, and so the code is represented by point B U + 0042. .. and so on, the Chinese character "you" character representation is "U + 4F60" ...

URL here to share a turn unicode code points: the code point conversion

You can see very detailed characters in the website in

Range codepoint

Code point range is presently U + 0000 ~ U + 10FFFF, theoretical size 10FFFF + 1 = 110000 (+1 Why, because starting from 0).

Mechanism 16, the latter is representative of one (16 4 th) 65536, as hexadecimal, so the first one is a 16 times after a 1, so the total size of 1 × 16 + 1 = 17 th 65536 , a rough estimate of 17 × 6 = 1,020,000 million, so this is a number of one million level.

In order to better manage such a large classification code points to 65,536 yards per point as a plane , a total of 17 planes.

而代理区就在平面里面,而平面又有很多讲究。

平面,BMP,SP

什么是平面?

由前面可知,码点的全部范围可以均分成 17 个 65536 大小的部分,这里面的每一个部分就是一个平面(Plane。编号从 0 开始,第一个平面称为 Plane 0。

什么是 BMP?

第一个平面即是 BMP(Basic Multilingual Plane 基本多语言平面),也叫 Plane 0,它的码点范围是 U+0000 ~ U+FFFF。这也是我们最常用的平面,日常用到的字符绝大多数都落在这个平面内。

(上图中第一个花花绿绿的平面就是 BMP。)

UTF-16 只需要用两字节编码此平面内的字符。

最常用的 BMP,它的码点空间也有 6 万多,如果把这些字符都放到一张图片上,会是什么情况呢?GNU Unifont 就制作了一张这样的图片。

下图是它的一个缩略版本:

什么是增补平面?

后续的 16 个平面称为 SP(Supplementary Planes)。显然,这些码点已经是超过 U+FFFF 的了,所以已经超过了 16 位空间的理论上限,对于这些平面内的字符,UTF-16 采用了四字节编码。

代理区

你可能还注意到前面的 BMP 缩略图中有一片空白,这白花花一片亮瞎了我们的猿眼的是啥呢?这就是所谓的代理区(Surrogate Area)

可以看到这段空白从 D8~DF。其中前面的红色部分 D800–DBFF 属于高代理区(High Surrogate Area),后面的蓝色部分 DC00–DFFF 属于低代理区(Low Surrogate Area),各自的大小均为 4×256=1024。

unicode码点替换为dc00的字符详情:“Non Private Use High Surrogate, First”,说明是高代理的意思,而 DC00 刚好就在 D800–DBFF这个高代理区里面

UTF-16如何用代理区编码?

UTF-16 是一种变长的 2 或 4 字节编码模式。对于 BMP 内的字符使用 2 字节编码,其它的则使用 4 字节组成所谓的代理对来编码。

在前面的鸟瞰图中,我们看到了一片空白的区域,这就是所谓的代理区(Surrogate Area)了,代理区是 UTF-16 为了编码增补平面中的字符而保留的,总共有 2048 个位置,均分为高代理区(D800–DBFF)和低代理区(DC00–DFFF)两部分,各1024,这两个区组成一个二维的表格,共有1024×1024=210×210=24×216=16×65536,所以它恰好可以表示增补的 16 个平面中的所有字符。

什么是代理对?

一个高代理区(即上图中的Lead(头),行)的加一个低代理区(即上图中的Trail(尾),列)的编码组成一对即是一个代理对(Surrogate Pair),必须是这种先高后低的顺序,如果出现两个高,两个低,或者先低后高,都是非法的。

在图中可以看到一些转换的例子,如

(D8 00 DC 00)—>U+10000,左上角,第一个增补字符

(DB FF DF FF)—>U+10FFFF,右下角,最后一个增补字符

UTF-16为何要采用代理对?

最开始是采用定长二字节方案,但是无法满足容量增长,因为两个字节也就216 = 65536个而已,我们的汉字就比这65536还多,怎么办?扩充!

于是转向定长四字节,但是转到4个字节虽然解决了容量的问题,又会引发了效率危机,比如一个字符A用一个字节就够存了,非要用4个字节存,之前1G的·文件现在可能要4G去存,费钱又费空间

于是各路大牛建立自己的编码方案,力图在效率和容量上取到一个平衡,其中一位大牛建立了UTF-16的编码方案!

看下面这个图,可以看到编码不是递增的,70-89的编码没有与之对应的字符。

这里挖出 70-89 间的码位,形成横竖 10×10 的编码空间,使得能再扩展 100 个编码空间。原来 2 位 100 个空间损失了 20,70-89是20个,这部分不参与编码,所以少了20个。

但是这20个编码通过形成 代理对 的方式又新增了100个代码空间,一来一回多了 80。这样一种变长方式也就是 UTF-16 所采用的。

UTF-16相当于牺牲了高代理区(D800–DBFF)和低代理区(DC00–DFFF)两部分空间,但是确新增了1024*1024=16*65536的空间。依次来实现了扩容。

码点到 UTF-16 如何转换?

继续上个例子。转换分成两部分:

1. BMP 中直接对应,无须做任何转换,也就是如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数;

2. 增补平面 SP 中,则需要做相应的计算。也就是如果U≥0x10000的情况

我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。

Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:1101100001000011 1101110000110000,转换为16进制即0xD843 0xDC30。

注意:以上计算方式仅用于说明转换原理,不代表实际采用的计算方式。UTF-32

UTF-32

我们说码点最大的 10FFFF 也就 21 位,而 UTF-32 采用的定长四字节则是 32 位,所以它表示所有的码点不但毫无压力,反而绰绰有余,所以只要把码点的表示形式以前补 0 的形式补够 32 位即可。这种表示的最大缺点是占用空间太大。

再来看稍复杂一点的 UTF-8。

UTF-8

UTF-8的好处

如果问你如何设计编码,你会说按照数字递增进行编码

例如下图,虽然简单,但起码也是一种编码

但是这种方法有点问题,想法很美好,它试图跟随编号来自然增长,它还是可以编码的,但在解码时则遇到了困难。

可见,由于低位的码位被“榨干”了,导致单个位与多位间无法区分,所以这样是行不通的。

我们做一下改进

这种编码方案,既然之前的无法区分,那我就把低位空间腾出来,5 及以上的就不使用了5,6,7...到49这些编码都不使用了,直接跳到50。然后引入一条变长解码规则:

从左向右扫描,读到 5 以下数字按单个位解码;读到 5 或以上数字时,把当前数字及下一个数字两位一起读上来解码。

实例:

从左向右扫描,读到 5 以下数字按单个位解码;读到 5 或以上数字时,把当前数字及下一个数字两位一起读上来解码。

这还是非常粗糙的设计,如果我们想在这串字符中搜索“o”这个字符,它的编码是 3, 首先会找到3和53,这样在匹配时也会匹配上 53 中的 3,这种设计会让我们在实现匹配算法时不好实现。

其实关键就在于用高位保留位来做区分,缺点就是有效编码空间少了。

UTF-8 是变长的编码方案,可以有 1,2,3,4 四种字节组合。UTF-8 采用了高位保留方式来区别不同变长,如下:

可以看到,由于最高位不同,多字节中不会包含一字节的模式。对于 UTF-8 而言,二字节的模式也不会包含在三字节模式中,也不会在四字节中,三字节模式也不会在四字节模式中,这样就解决上面所说的搜索匹配难题。

这也每当进行搜索的时候,每个二字节和三字节的编码没有重叠,因为最高位不同呀~所以不会出现搜索同一个出现两个的结果。不过就是有效编码空间少了。

UTF-8如何与码点进行转换

Unicode编码(十六进制) UTF-8字节流(二进制)
000000-00007F 0xxxxxxx
000080-0007FF 110xxxxx 10xxxxxx
000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF 11110xxx10xxxxxx10xxxxxx10xxxxxx

对于Unicode的编码首先确定它的范围,找到它是对应的几字节。

对于0x00-0x7F之间的字符,UTF-8编码与[ASCII编码]完全相同。

“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

所以替换完之后呢,加粗的就是3字节模板的固定数字,而其余就是把0x6C49的二进制数从左到右依次填写进去

最后再分享一个网站:Unicode

发布了46 篇原创文章 · 获赞 39 · 访问量 4万+

Guess you like

Origin blog.csdn.net/weixin_42128813/article/details/103772699