简单介绍Unicode和utf编码

Unicode是一个字符集,码点范围为U+0000~U+10FFFF,共有1+2^20的取值空间,可以容纳超过100万个字符,至少需要21Bit(位)编码空间。

码点的意思是,这个字符集内的字符按序编号,编号号码为从0增加到0x10FFFF,每个字符唯一对应一个码点值

比如字符'0'的码点值为0x30,'ȸ'的码点值为0x238,'大'的码点值为0x5927,"🎵"的码点值为0x1f3b5

可以看到这些码点值,所需的字节大小从1字节到3字节不等,怎么记录这么码点值呢?有以下方法:

1、最容易想到的方案,按最长的3字节来,又因为字节对齐的原因,每个码点值使用四个字节表示,这就是UTF-32,方案最简单,缺点也很明显,大量常用的字符用一两个字节就可以表示了,浪费空间

为消除方案一的缺点,可以划分出来较少字节的模块给高频字符使用,比如ASCII字符集只有128个,7Bit即可表示,表示ASCII只需要一个字节。(实际上Unicode的码点起始位置就是ASCII,即码点U+0000~U+007F的码点值和ASCII值相同,这是为了兼容历史已有的字符)。沿着这个思路就有了UTF-8和UTF-16的编码方式

2、UTF-8编码可以为每个Unicode字符采用1、2、3、4个字节。为了表示字符使用了几个字节,UTF-8采用了前缀标记位。具体为(1或0表示前缀标记位,x表示编码区):

10xxx xxxx7个有效位,可以容纳2^7=128个字符
2110x xxxx 10xx xxxx5+6=11个有效位,可以容纳2^11=2048个字符
3

1110 xxxx 10xx xxxx 10xx xxxx

4+6+6=16个有效位,可以容纳2^16=65536个字符
41111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx3+6+6+6=21个有效位,可以容纳2^21个字符

前缀标记位的作用是标识一个字符占了几个字节,因为UTF-8编码可以灵活的采用1~4字节表示Unicode码点值,所以前缀标记位在UTF-8编码中,是必不可少的。

UTF-8区分编码,相对于UTF-32,可以为低码点值的编码节省空间0~3个字节,是目前使用最广泛的编码方式。但是UTF-8编码浪费了不少空间给前缀标记位,使得两个字节只有2048+128个容值空间。最复杂的UTF-16编码来了!

3、UTF-16使用双字节或者四个字节表示一个Unicode码点值,是三种编码中最复杂的编码方式。UTF-16无编码前缀,而是划分了一块取值空间(叫做代理区Surrogate,和Proxy不同,Surrogate强调非有不可)用来区分某个码点值是用了两个字节,还是用了四个字节。这块取值空间用了12位的空间,有2048个值。具体来说就是,双字节的高位字节,如果值为D8~DF之间,就表示这个Unicode码点值不是一个双字节能表示完的,需要两个双字节也就是四字节表示。

四字节具体如何编码呢?高位的双字节为HXXX,低位的双字节LXXX。依前文所述,HX和LX的值应为D8~DF之间,UTF-16又规定:HX值为D8~DB(1101 1000~1101 1011,即1101 10xx),LX值为DC~DF(1101 1100~1101 1111,即1101 11xx)。可以看到HX和LX各有两位还空着,这四位有2^4=16个值域空间,就代表UTF-16的16个扩展平面,每个扩展平面可以容纳2^16=65536个码点值。较少有语言的字符数量会超过这个数,如果超过了,就多分配扩展平面。多个相近语言的字符,编码公用同一个平面是更常见的。具体扩展平面列表可以查看Unicode的说明。

开篇说了Unicode的码点值需要21位才能表示完,UTF-32和UTF-8都已经满足了值域空间的要求。UTF-16是怎么满足的呢?U+0000~U+FFFF(除U+D800~U+DFFF外)表示基本平面,四字节如何编码U+10000~U+10FFFF呢?1101 10xx  xxxx xxxx的高位和1101 11xx  xxxx xxxx的低位,加起来有20位的编码空间,而U+10FFFF需要21位,如何处理呢?答案也很简单,将扩展平面的所有码点值,统一减去U+10000即可,这样只需要表示U+00000~U+FFFFF,解码时再统一加回。将码点值20位平分两半,各自放到高位区和低位区。

可以看到,UTF-16没有采用前缀标志位,而是使用了特定的代理区来区分常用的基本面和扩展面,基本面只“浪费”了 2 / 64的值域空间(6Bit中区分出了110110和110111, 2 / 2^6),使得常用的基本面可以表示更多的字符。

有很多博文已经详细介绍了具体的UTF-16的编解码算法,这儿就不在陈述。

总结来说,Unicode是字符集,UTF-8、UTF-16、UTF-32是Unicode字符集的编码实现方式。

Unicode的码点值范围是从U+0000~U+10FFFF,但不是每一个值都有对应的字符,有空白区,可以容纳未来的字符。同样,三种编码方式的有效值域空间也不是全都有对应的字符。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值