推荐一篇文章,此博客是阅读这篇文章后自己的一些总结与理解
Unicode
Unicode是一种标准,他收集了世界上所有的字符,并为每个字符分配了一个唯一的码点
现在来看看Unicode字符集是长什么样子,由于全球所有的字符太多太多,按照字符的类型使用频率把字符分了17个平面,如图,每个平面的码点唯一对应一个字符(当然也有还没用到的,因为实际上字符并没有那么多),像平面0上的码点就放着最常用的字符
拿平面0举例,我们常用的字符 A 就在平面0上,A对应的字符编码是0041,即图中平面0的0000-0FFF中的0041,
- 这个0041就是码点
- 这个0000-10FFFF就是码点空间
- 0000-10FFFF与全球字符的对应关系就是编码字符集
专业术语概念
- Coded Character Set(CCS):编码字符集,将全球的字符收集起来每个分配唯一的字符编号,Unicode字符集就是一种编码字符集
- Character Encoding Form(CEF):将ccs中的字符编号按照某种规则转化成二进制序列,UTF8、UTF16就是一种字符编码表
- Code Point:码点,即ccs中的字符编号
- Code Unit:代码单元,已编码的文本中具有最短bit位的单元,UTF8是8bit长,UTF16是16bit长(至于UTF8为什么是8bit,UTF16为什么是16bit,后面还会介绍)
- Code Space:码点空间,所有码点的集合
- 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唯一表示一个字符。
组合规则如图:
由于查表麻烦,所以设计了一种算法来根据码点计算出他对应的高代理低代理
拿编码点10401举例:
- 0x10401-0x10000-0x401,
- 0x401转化为20位二进制为 0000 0000 0100 0000 0001
- 一分为二,x=0000 0000 01 ,y = 00 0000 0001
- H = 0000 0000 01+ 0xD800 == 0000 0000 0000 0001 + 1101 1000 0000 0000 = 1101 1000 0000 0001 = 0xD801
- L = 00 0000 0001+ 0xDC00 == 0000 0000 0000 0001 + 1101 1100 0000 0000 = 1101 1100 0000 0001 = 0xDC01
- UTF16结果: 0xDB01DC01
和UTF16代理对对应
UTF8
UTF8更简单了,请看图:
- 首个位为0,表示这个UTF8是一个字节,他表示的码点在0000-007F范围里,图中的x位置,用于放置码点转成二进制对应的值 (单个字节和ASCII表示的方式一模一样)
- 首个字节为1,表示是多个字节,有多少个1表示用了多少个字节表示这个码点,以0结束
- 如果结构是10…表示他是某个码点的中部或屁股
- 比如0080用了2个字节,那么第一个字节是110xxxxx 剩下那个字节10xxxxxx,将0080转换成二进制为 0000 0000 1000 0000 ,放入110 00010 10 000000 ,其中斜体部分才是码点寸的值
来源:CSDN
作者:ai_pple
链接:https://blog.csdn.net/ai_pple/article/details/103702474