Unicode、UTF8、UTF16

推荐一篇文章,此博客是阅读这篇文章后自己的一些总结与理解

Unicode

Unicode是一种标准,他收集了世界上所有的字符,并为每个字符分配了一个唯一的码点

现在来看看Unicode字符集是长什么样子,由于全球所有的字符太多太多,按照字符的类型使用频率把字符分了17个平面,如图,每个平面的码点唯一对应一个字符(当然也有还没用到的,因为实际上字符并没有那么多),像平面0上的码点就放着最常用的字符
Unicode 平面分布和码点空间
拿平面0举例,我们常用的字符 A 就在平面0上,A对应的字符编码是0041,即图中平面0的0000-0FFF中的0041,

  1. 这个0041就是码点
  2. 这个0000-10FFFF就是码点空间
  3. 0000-10FFFF与全球字符的对应关系就是编码字符集

专业术语概念

  1. Coded Character Set(CCS):编码字符集,将全球的字符收集起来每个分配唯一的字符编号,Unicode字符集就是一种编码字符集
  2. Character Encoding Form(CEF):将ccs中的字符编号按照某种规则转化成二进制序列,UTF8、UTF16就是一种字符编码表
  3. Code Point:码点,即ccs中的字符编号
  4. Code Unit:代码单元,已编码的文本中具有最短bit位的单元,UTF8是8bit长,UTF16是16bit长(至于UTF8为什么是8bit,UTF16为什么是16bit,后面还会介绍)
  5. Code Space:码点空间,所有码点的集合
  6. BOM(Byte Order Mark):字节序,表示字节的顺序,将来怎么存取转化后的二进制序列,分为大头方式小头方式

字符编码表

按照不同的规则将码点转换成二进制,像UTF8、UTF16就是不同的规则来转换码点

UTF16

最先开始字符还没收集到那么多的时候,只有平面0那么多码点,所以用的比较粗暴的方式,直接将码点转换成二进制(码点是16进制嘛,直接将它变成二进制),比如000F这个码点对应的二进制就是0000 0000 0000 1111,这种方式叫UCS-2,用固定的2个字节来表示
后来字符开始变多,平面有17个平面之后,这种方式就表示不了了,于是UTF16就诞生了

UTF16的平面0还是按照UCS02的方法编码,平面1-17就采用了一个叫代理对的方式。

这里补充一个知识点,平面0上0xD800~0xDFFF是没有对应的字符的,也就是这个区间没有用上,于是UTF16把这区间一分为二,0xD800~0xDBFF(叫高代理码点),0xDC00-0xDFFF(叫低代理点),一个高代理和一个低代理组合成的二进制来表示高平面的码点,即0xD800DC00转换成的二进制为1101 1000 0000 0000 1101 1100 0000 0000 来表示码点10000,这个码点10000唯一表示一个字符。

组合规则如图:
UTF-16 代理对
由于查表麻烦,所以设计了一种算法来根据码点计算出他对应的高代理低代理

增补平面的码点值减去0x10000
得到的结果转换为20位二进制,一分为二,分为高10为x和低十位y
高代理位:H = x + 0xD800,低代理位: L = y + 0xDC00
UTF16编码结果: HL

拿编码点10401举例:

  1. 0x10401-0x10000-0x401,
  2. 0x401转化为20位二进制为 0000 0000 0100 0000 0001
  3. 一分为二,x=0000 0000 01 ,y = 00 0000 0001
  4. H = 0000 0000 01+ 0xD800 == 0000 0000 0000 0001 + 1101 1000 0000 0000 = 1101 1000 0000 0001 = 0xD801
  5. L = 00 0000 0001+ 0xDC00 == 0000 0000 0000 0001 + 1101 1100 0000 0000 = 1101 1100 0000 0001 = 0xDC01
  6. UTF16结果: 0xDB01DC01

和UTF16代理对对应

UTF8

UTF8更简单了,请看图:
UTF-8 编码方式

  1. 首个位为0,表示这个UTF8是一个字节,他表示的码点在0000-007F范围里,图中的x位置,用于放置码点转成二进制对应的值 (单个字节和ASCII表示的方式一模一样)
  2. 首个字节为1,表示是多个字节,有多少个1表示用了多少个字节表示这个码点,以0结束
  3. 如果结构是10…表示他是某个码点的中部或屁股
  4. 比如0080用了2个字节,那么第一个字节是110xxxxx 剩下那个字节10xxxxxx,将0080转换成二进制为 0000 0000 1000 0000 ,放入110 00010 10 000000 ,其中斜体部分才是码点寸的值
发布了40 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ai_pple/article/details/103702474