本文正在参加「金石计划 . 瓜分6万现金大奖」

不知道你是否了解 Unicode ,它为每一个字符供给了唯一的编号。简略的说,Unicode 便是一个 Map,保存了编号与字符之间的映射。但是,咱们在开发过程中接触最多的是 UTF-8,不是 Unicode 编码。有 Unicode 编码不就够了吗?为什么咱们需求 UTF-8 呢?

为什么只需 Unicode 是不可的

在答复这些问题前,无妨先尝试自己为字符编码。简略起见,这里咱们用十进制来为字母表编码:

a -- 1
b -- 2
c -- 3
...
z -- 26

如果用上面的编码表明 add 这个单词,成果便是 144。1 对应 a,4 对应 d,十分简略对不对。

当咱们需求表明 hello 时,成果便是 85121215 。这时你发现问题了没有,85121215 这个编码成果还可以表明 heababoheababaeheablo等等 。也便是说,这个编码成果可以对应几种不同的字符串,这是不能接受的。

有了 Unicode ,为什么还需要UTF-8

从图中咱们可以看出,1215 在解析过程中可以表明不同的字符组合,这就导致了成果的差异。咱们这里还仅仅是对 26 个字母进行编码,而 Unicode 目前已编码数量超过了十几万种。看到这里,对于第一个问题,你应该已经知道为什么只需 Unicode 是不可的了。

为什么需求 UTF-8

上面说完了原因,现在看下处理方法。其实要处理这个问题十分简略,有两种思路:

  1. 第一种是固定位数解析:如固定两位解析,缺乏的补0。这时 hello 的编码成果就为 0805121215
  2. 第二种是添加标志位:如最简略的加空格,这时 hello 的编码便是 8 5 12 12 15

在 Unicode 中,处理方案叫 UTF(Unicode transformation format),有三种方法分别是 UTF-8、UTF-16、UTF-32。UTF-32 是第一种思路,固定 32 位解析,缺乏补0;UTF-8、UTF-16 则是第二种思路。目前不同的方法都有运用,比方 python3 用的是 UTF-32,Java 默认是 UTF-16,网络数据传输大部分都是 UTF-8。这就答复了第二个问题,咱们运用 UTF-8 是为了处理上面解析 Unicode 呈现的问题。

说了这么久的UTF-8 ,这里咱们就来看看它的编码规矩。UTF-8 的编码规矩如下:

有了 Unicode ,为什么还需要UTF-8

这里先解释下表格的意思:

xxx Byte 表明第几个Byte(每个Byte有8位),它们下面的字符串中 x 表明任意 0 或许 1,如 0xxxxxxx 可以是 00000000 , 也可以是 01000000,只需前面的“标头”是 0 就可以。这里的这里“标头”就相当于前面咱们的空格,都是为了让计算机能正常的解析。

Number of Free Bits 表明最大表明的位数,Max Expressible Unicode Value 表明最大编码数,比方第一行最大位数是 7,它的最大编码便是 2 ^ 7 – 1 = 127。根据这个咱们就能知道运用哪一行的格局进行编码,例如中文是 16 位长的,第 1 、2行的位数不可,因此只能用第三行。这里以 这个字为例:

**汉**的 Unicode 编码为:                            U+6C49
**汉**对应的二进制为(这里空格是方便看才加的):            01101100 01001001

因为 的 Unicode 的编码位数是 16 位的,因此选择第三行 1110xxxx 10xxxxxx 10xxxxxx(这里的空格是方便看才加的)

有了 Unicode ,为什么还需要UTF-8

如上图的方法对 进行编码,成果为 11100110 10110001 10001001

总结

这里咱们实现了一套简略的编码,在解析过程中,咱们发现只需对字符的映射是不可的。咱们还需求一套编码方法,让解析的成果可以唯一。在 Unicode 中,这种编码方法叫做 UTF(Unicode transformation format),其间最有名的便是 UTF-8 。这也是咱们有了Unicode,还需求UTF-8的原因。文章最终求求免费的赞吧。

参考

  • What is Unicode?
  • UTF-8, UTF-16, UTF-32 & BOM