unicode、utf-8 编码原理
2019-08-06 本文已影响0人
苦苦修行
本文不涉及具体细节,只泛泛而谈。
本文全是大白话,也就是说,可能很多用词不那么专业。但是,懂了就达到目的了。以后再去看专业的文章,就会觉得容易多了。
本文是在研读了阮一峰和知乎网友的基础上写作的。
相关链接为:
字符编码笔记:ASCII,Unicode 和 UTF-8
Unicode 编码及 UTF-32, UTF-16 和 UTF-8
注意:勿要纠结于我举的例子,我知道是错的,在本文中仅为阐述思想。
以下为本人的心得:
为何会出现 unicode?
- 为了让文字在电脑上显示,必须给每个字符编个号码,比如我给字母
a
编号为1
,字母b
编号为9999
。 - 那么问题来了,在中国可能给汉字
人
编号为1
,在美国可能给字母a
编号为1
,如果中美两国交流,这个编号1
到底该解读成人
还是a
? - 为了解决这个问题,就要在世界范围内统一编号,把世界上所有的字符都包含进来,设置一个唯一的编号。比如编号
1
只能表示a
,不能有其它的表示。那么这个方案就是 unicode,从名字上也能看出来,是统一的编号。
为何又要出现 utf-8等?
- 在 unicode 方案中,最常用也是最基本的,只用两个字节编号,就包含了世界上主要的文字了。如果用三个字节编号,那就是 unicode 扩展部分的了。(unicode 有 17 个平面
(Plane 0 - Plane 16)
,我们最常用的就是Plane 0
,(Plane 1 - Plane 16)
就是扩展平面。说白了,扩展平面就是要用三个字节来编码了,Plane 1
的最高位字节值是 1,依次类推,Plane 16
的最高位字节值是 16,用 16 进制就是 10) - 如果直接用 unicode 的编号来存储字符,最少也要用到两个字节,这会有什么问题呢?人家西方字符,明明用一个字节就已经够够的了,非要用两个字节存储太浪费资源了。
- 于是就有了 utf-8 编码方案。如果是西方字符就用一个字节存储,如果是汉字等就用两到三个字节存储。这样就都兼顾到了。
utf-8实现原理通俗讲解
- 但是等等,你 utf-8 一会用一个字节,一会用两个三个字节,我计算机怎么知道你是几个字节表示一个字符呢?
- 来看 utf-8 是怎么设计的。如果是西方字符,就用一个字节表示,字节的最高位是 0(好像西方字符总共是 128 个,用不到最高位)。如果是汉字,把它的 unicode 编号展开为二进制(给它起个代号,就叫 2B 吧)。utf-8 生成一个这样的玩意儿(给它起个代号,就叫 wy 吧):
1110xxxx 10xxxxxx 10xxxxxx
, 你从2B的最低位开始,一个个的往 x 里放(也是从最低位开始),如果x 没放完,用 0 补全。 utf-8 在设计 wy 的时候,要让每个字节的 x 用到了(注意这句话,并不意味着每个x 都被用到)。然后把这个 utf-8 的编码就存到文档里了。 - 用 utf-8 编码方案用读这个文档的时候,它就开始这样解析了。如果一个字节最高位是 0,说明这一个字节就表示一个西方字符。如果一个字节最高位是1110这样的,说明连同它自己,接下来的三个字节表示一个字符,然后再把这三个字节 x 位上二进制取出来连在一起,这不就是一开始的那个2B吗。然后用这个 2B 的值(就是 unicode 的编号)去电脑系统里的unicode 表里找到对应的字符显示出来。
- 通过以上说明,你大概也看出来了:utf-8 这类编码方案,存的时候,是用 utf-8 自己的设计,把 unicode 编号变为自己可以解析的编号。读的时候,再把 utf-8 的编号还原成 unicode 编号,用unicode 编号去电脑里查字符,然后把字符显示出来。其它编码方案也是这个思路。