对于我来说,字符集的相关知识,一直都是噩梦。Unicode、utf-8、ASCII….搞得头都大了。我也特意梳理了下,字符集之间的关系。而且,之前在贝壳面试,面试官也问了我关于unicode编码的事情。

ASCII

由来

ASCII的字符集算是出来最早的了,最初是来源于美国。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符。除了我们常见的英文字母,还包含了各种英文的标点符号等等。在英语中,用128个符号编码便可以表示所有,但是用来表示其他语言,128个符号是不够的。

存在的问题

但是这样是有问题的。举个例子,法语的字母上方是有音标的,它就无法使用ASCII的编码表示。于是,一些欧洲的国家决定,利用字节中闲置的最高位编入新的符号,这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。由最开始的 0xxx xxxx (2^7=128) 变成了 1xxx xxxx (2^8=256)

Unicode

后来,大家都在考虑,如果有一种字符集,能够包含所有的字符,那就好了。

于是,在 1991 年,国际标准化组织和统一码联盟组织各自开发了 ISO/IEC 10646(USC)和 Unicode 项目。他们俩的野心和当时的秦始皇一样,一统江湖。后来,两个组织开始进行讨论,决定把彼此的工作内容合并,但是项目还是独立存在,各自发布自己的标准,但是要保持兼容。后来由于Unicode的好记,就被广为流传。其实,Unicode的含义可以解释为union code。

在表示一个Unicode的字符时,通常会用U+ 后面跟着十六进制的数字来表示这一个字符。

Unicode的编码,延续了ASCII的编码,0-127位,还是代表了ASCII的编码,从128以后,才是其他的编码。

比如 在unicode的U+ 0041代表了大写的A, 在ascii编码16进制也是\x41

再比如,的unicode编码表示为U+ 80a5

UTF-8

utf-8的的全拼是Universal Character Set/Unicode Transformation Format,翻译过来就是Unicode格式化,很明显是一个动词,表示把字符转换成8位的Unicode。

举个例子:

I’m 肥龙

使用unicode的表示为

I U+49
' U+20
m U+6D
肥 U+80A5
龙 U+9F99

但是,在计算机里,统一都是2进制的存储的,所以转换成2进制表示为

I  00000000 01001001
'  00000000 00100000
m  00000000 01101101
   00000000 00000000
肥  10000000 10100101
龙  10011111 10011001

UTF-8规定:

1、单字节的字符,字节的第一位设为0,对于英文文本,utf-8只占用一个字符,所以第一位都是0

2、n个字节,第一个字节的前n个设为1,第n+1设为0,后面的字节前两位都设为10,这n个字节的其余空位填充该字符unicode码,高位用0补足。

所以,转换成UTF-8过程

肥
---------------------------
10000000 10100101   二进制
1110 10 10         初始化模板
11101000 10000010 10100101 补全
e8 82 a5            16进制
龙
---------------------------
10011111 10011001 二进制
1110 10 10          初始化模板
11101001 10111110 10011001 补全
e9 be 99            16进制

所以最后的转换成utf-8的编码

I  01001001
'  00100000
m  01101101
   00000000
肥  11101000 10000010 10100101
龙  11101001 10111110 10011001

使用Python验证一下结果

>>> a=u'肥龙'
>>> a
u'\u80a5\u9f99'
>>> b=a.encode('utf8')
>>> b
'\xe8\x82\xa5\xe9\xbe\x99'
>>>

可以看到,省略了一部分空间。汉子的编码多了一个字节,英文的编码少了一个字节,总共节省了2个字节的空间!

本文连接: https://feilong.tech/2019/11/08/ascii_unicode_utf-8

发表评论

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