00 01 02 03 04 05 06 07 08 0A 0B 0C 0D 0E 0F 10 |
因而按照扩展位,划分了17个维度,这每一个维度,叫作一个平面
17个平面,编号从 0~16
|
每一个平面 65536个字符 |
17个平面,扩展后总共能够表示1114112个字符 |
扩展后的范围为
U+000000 ~ U+10FFFF
|
听起来可能有点迷惑,不是知道具体的值了么?怎么还不知道如何表示? 好比数字1 他的码点是1 假如我用两个字节来存储,每一个字节的前两位我当作其余的标志位, 设置为11 那么可能结果是这样子的11000000 11000001 显然,他的值并非1 编码方式只是能够保证,你的字符是按照指定的字符集进行编码的 也就是说若是你告诉我拿出来码点为1 的,我会把1100 0000 1100 0001 解析成数字1 可是并不能保证我保存的数据就是他的码点的真值,0000 0001 ,中间形式是编码方式说了算的 最直观的例子就是网络中报文的传输,都会附加本身的头信息 因此中间传输的数据并非跟你发送的数据如出一辙,中间的数据就是编码形式的存储 可是,接收端接受解析后,就是跟你发送的数据同样的,这就好像是你的字符 |
UTF-8 是变长
UTF-32 是定长
UTF-16介于他们之间 2个字节或者4个字节
|
UTF-16编码以16位无符号整数为单位 |
咱们把Unicode编码记做U 编码规则以下
若是U<0x010000, 也就是0x000000 ~ 0x00FFFF
U的UTF-16编码, 就是U对应的16位无符号整数
|
若是U≥0x010000 也就是0x010000 ~ 0x10FFFF 咱们先计算下 U'=U-0x010000 能够得出来 U' 范围是 0x000000 ~ 0x0FFFFF 显然, U'的最大值为0xFFFFF 也就是最多20个1 也就是能够被写成20个二进制位 既然是20个二进制位,那么咱们是否是能够把它拆分红两组呢? 每组10个二进制位 00 0000 0000 它能表示的范围是2的10次方=1024个 BMP是2个字节,16位, 很显然,若是把U' 拆分红两组,每组10个二进制位的话 每个都可以保存到2个字节内 因此Unicode标准规定:基本多语言平面内,U+D800..U+DFFF的值不对应于任何字符,为代理区 ,其中又分为高代理区和低代理区 U+D800 加上10个二进制位的数值的最大值,能够获得高代理区的范围 U+D800 --->1101 10 00 0000 0000 + 0000 00 11 1111 1111 = 1101 1011 1111 1111 = 0xDBFF 下一个就是0xDBFF +1 = 0xDC00,因此低代理区从0xDC00 开始 0xDC00 加上10个二进制位的数值的最大值,能够获得低代理区的范围 0xDC00----> 1101 1100 0000 0000 + 0000 00 11 1111 1111 = 1101111111111111 = 0xDFFF |
高代理区范围 U+D800 ~0xDBFF 低代理区范围 0xDC00 ~ 0xDFFF 代理区间是U+D800....U+DFFF |
因此UTF-16的编码方式就是 先计算 U'=U-0x010000 而后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx 而后分别计算高位代理和低位代理 U+D800 --->1101 10 00 0000 0000 + 0000 00 yy yyyy yyyy = 1101 10 yy yyyy yyyy 0xDC00----> 1101 1100 0000 0000 + 0000 00 xx xxxx xxxx = 1101 11xx xxxx xxxx |
再精简下步骤 1. 先计算 U'=U-0x010000 2. 而后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx 3.两个值为 1101 10 yy yyyy yyyy / 1101 11xx xxxx xxxx |
以前咱们提到过,Unicode中的一个字符的值,被称之为一个码点
显然,一个码点,可能被一个代码单元存储,也可能被两个连续的代码单元存储
|
在内存中0x01020304的存储方式
内存地址 4000 4001 4002 4003
BE 01 02 03 04
LE 04 03 02 01
|