郑州网站开发招聘,小而美企业网站建设,教务系统管理,宁波公司网站开发招聘1.
首先要注意的是#xff0c;代理Surrogate是专属于UTF-16编码方式的一种机制#xff0c;UTF-8和UTF-32是不用代理的。
如前文所述#xff0c;为了让UTF-16能继续编码基本平面后面的增补平面中的码点值#xff0c;于是扩展了UTF-16编码方式。
具体的扩展方法就是为其增…1.
首先要注意的是代理Surrogate是专属于UTF-16编码方式的一种机制UTF-8和UTF-32是不用代理的。
如前文所述为了让UTF-16能继续编码基本平面后面的增补平面中的码点值于是扩展了UTF-16编码方式。
具体的扩展方法就是为其增加了代理机制用两个对应于基本平面码点(即BMP代理区中的码点)的16位码元来表示一个增补平面码点这两个用来表示一个增补平面码点的特殊16位码元就被称为“代理对”。
如果要用简单的一句话来概括就是——所有大于0xFFFF的码点值(即增补平面码点编号范围为0x10000~0x10FFFF十进制为65536~1114111注意0xFFFF是十六位二进制数的最大值的十六进制表示)要编码成UTF-16编码方式的话就必须使用代理机制(也就是用代理对来表示)。
2.
在UTF-16编码方式中被合起来称为“代理对”的这两个16位码元就其中的任一单个码元而言其实就直接对应于基本平面BMP中的某一个码点(即BMP中每一个码点的值必然对应于一个16位码元的值因为基本平面中的码点总数为2^1665536个而16位码元能表示的值也等于2^1665536个)。
这样一来就产生了冲突某个UTF-16码元到底是用于表示基本平面字符的码元还是用于表示增补平面字符的代理对中的代理码元
因此为避免冲突这些被用作“代理”的任一码元所对应的码点在基本平面中均未定义字符即均没有指定字符。且形成“代理对”的两个码元所对应的码点其编号必定是连续的。
“代理”的真实含义或许就在于此用两个基本平面中未定义字符的连续码点合起来“代为署理”增补平面中的码点。
因此基本平面中这些用作“代理”的码点区域就被称之为“代理区(Surrogate Zone)”其码点编号范围为0xD800~0xDFFF(十进制55296~57343)共2048个码点。
3.
增补平面一共有16个平面(即第2平面~第17平面)码点编号范围为0x10000~0x10FFFF(十进制为65536~1114111码点总数为1048576个)。用两个代理码元表示第一个码元的取值范围为0xD800~0xDBFF(二进制为1101 1000 0000 0000 ~ 1101 1011 1111 1111十进制为55296 ~ 56319)第二个码元的取值范围为0xDC00~0xDFFF(二进制为1101 1100 0000 0000 ~ 1101 1111 1111 1111十进制为56320 ~ 57343)。
因此增补平面的第一个码点的编号0x10000其UTF-16编码就是0xD800 0xDC00(即0x10000经UTF-16编码后的码元序列为0xD800 0xDC00)其余类推。展现为二进制形式后如下 代理码元1 代理码元2 1101 10pp ppxx xxxx 1101 11xx xxxx xxxx
其中代理码元1中的110110、代理码元2中的110111是定数p、x是变数。去掉定数后组合起来就是pppp xxxx xxxx xxxx xxxx共20位(2^201048576)刚好能够表示目前16个增补平面中的全部码点(0x10000~0x10FFFF共1048576个)。其中pppp共4位表示16个增补平面之一的编号(2^416)紧接着的16位x表示某个增补平面内的某个码点(2^1665536个码点而65536个码点/平面*16个平面1048576个码点)。
4.
按照上面的编码方式代理对里面的两个代理码元分别称之为高16位代理码元(或称为lead surrogates引导代理、前导代理)和低16位代理码元(或称为trail surrogates尾随代理、后尾代理)。
由于引导代理和尾随代理的值分别在0xD800~0xDBFF(十进制为55296 ~ 56319)之间和0xDC00~0xDFFF(十进制为56320 ~ 57343)之间所以首尾两个代理总共可以组合出(56319-552961)*(57343-563201)1048576个代理对也就是总共可以表示1048576个增补码点而目前Unicode标准所确定的16个增补平面的码点总和也就是65536*161048576个。
显然Unicode字符集作为开放式字符集未来不断增补字符进来以至于增补平面超过16个则按目前的UTF-16编码算法是无法编码的。也正是因为如此UTF-16编码方式的扩展性、适应性是不足的未来全面被具备高扩展性、高适应性的UTF-8编码方式代替是必然的。
笨笨阿林原创文章转载请注明出处
5.
从增补平面的码点值通过基本平面中的代理对编码为增补平面字符的码元序列的具体算法如下
1 增补平面中的码点值(0x10000~0x10FFFF二进制为0001 0000 0000 0000 0000~1 0000 1111 1111 1111 1111对应的码点名称为U10000~U10FFFF)减去0x10000(二进制为0001 0000 0000 0000 0000)可得到20位长的比特组(值的范围为0x00000~0xFFFFF二进制为0000 0000 0000 0000 0000 ~ 1111 1111 1111 1111 1111)
2将得到的20位长的比特组分拆为两部分高位10比特和低位10比特
320位长的比特组中的高位10比特(值的范围为0x000~0x3FF二进制为00 0000 0000~11 1111 1111)加上0xD800(二进制为1101 1000 0000 0000)得到第一个代理码元即引导代理(值的范围是0xD800~0xDBFF二进制为1101 1000 0000 0000 ~ 1101 1011 1111 1111)
420位长的比特组中的低位10比特(值范围也是0x000~0x3FF二进制为00 0000 0000~11 1111 1111)加上0xDC00(二进制为1101 1100 0000 0000)得到第二个代理码元即尾随代理(值的范围是0xDC00~0xDFFF二进制为1101 1100 0000 0000 ~ 1101 1111 1111 1111)
5将引导代理与尾随代理按前后顺序组合在一起成为“代理对”就得到了增补平面字符的码元序列。
例如增补平面中码点值为10437(码点名称为U10437)的字符(?)
10x10437减去0x10000结果为0x00437二进制为0000 0000 0100 0011 0111。
2分拆成高10位值和低10位值两部分0000000001(即0x0001)及0000110111(即0x0037)。
3添加0xD800到高位值以形成高位的引导代理0xD800 0x0001 0xD801(二进制为1101 1000 0000 0001)。
4添加0xDC00到低位值以形成低位的尾随代理0xDC00 0x0037 0xDC37(二进制为1101 1100 0011 0111)。
5将高位的引导代理与低位的尾随代理按前后顺序组合在一起成为“代理对”就得到了增补平面字符?(码点名称为U10437)的码元序列1101 1000 0000 0001 1101 1100 0011 0111。
6.
下表总结了该转换。不同的颜色表示码点值是如何被分布到UTF-16码元序列中的而由UTF-16编码过程中加入的代理附加位则以不同的红色(亮红色与暗红色)显示 7.
显然增补平面中的码点值从0x10000到0x10FFFF共计0xFFFFF 0x1个即1,048,576个刚好也就是需要20位来表示(2^201,048,576)。如果用两个16位长的码元组成的序列来表示意味着引导代理要容纳上述20位中的前10位尾随代理要容纳上述20位中的后10位。
另外还要能够根据每个16位码元来直接判断该码元到底是属于引导代理(标志位为前6位11 0110还剩下10位因此总个数为2^101024个)还是属于尾随代理(标志位为前6位11 0111也剩下10位因此总个数也是2^101024个)。
为避免冲突因此需要在基本多语言平面BMP中保留未定义Unicode字符的102410242048个码点就可以容纳引导代理与尾随代理所需要的编号空间(码点空间、代码空间)也就是16个增补平面所需要的编号空间共计1024*10242^201048576个码点。这BMP中的2048个码点对于BMP总计65536个码点来说仅占3.125%(2048/655360.03125)。 8.
在UTF-16编码方式中引导代理的后面应该是一个尾随代理而尾随代理的前面就应该是一个引导代理不能出现一个引导代理的后面是一个非代理的普通UTF-16码元的情况也不能出现一个引导代理的后面还是一个引导代理的情况。
UTF-16文本(字符串)的最后一个码元不能是引导代理不允许出现一个尾随代理的前面是一个尾随代理的情况也不允许出现一个尾随代理的前面是一个非代理的普通UTF-16码元的情况UTF-16文本(字符串)的第一个码元不能是尾随代理。
而单独的一个代理码元(不管是引导代理还是尾随代理)是不合法的代理必须以一个“引导代理尾随代理”编码对(即代理对)的形式出现。
笨笨阿林原创文章转载请注明出处
9.
UTF-16的这种“代理对”编码规则保证了文本处理程序能够正确地访问和处理包括了基本平面和增补平面在内的全部UTF-16码元序列并消除了基本平面字符和增补平面字符之间发生冲突的可能性。
因为引导代理和尾随代理码元被各自规定在一个特定范围内取值所以很简单的一个原则就是凡是在代理编码范围内的码元就是“代理”增补平面SP字符的“代理码元”否则就是“基本平面BMP字符的码元”。由于BMP中的字符码元和代理码元分别在各自独立的编码范围内进行编码所以对于一个符合格式规范的UTF-16码元来讲它必须满足以下条件 - 非代理码元(BMP字符码元)必须避开代理码元所占用的范围0xD800~0xDFFF(二进制为1101 1000 0000 0000 ~ 1101 1111 1111 1111共2048个) - 引导代理必须是代理对中的第一个码元 - 尾随代理必须是代理对中的第二个码元。
在处理UTF-16文本时为了确保文本数据的完整性绝对不能把任意一个代理从代理对中拆出来也不能在代理对中间插入另一个字符的码元或码元序列。
10.
在UTF-16编码方式里面一个Unicode字符码点值由一个或两个16位码元编码。所以如果想在一个UTF-16码元序列里面判断某个码元是属于哪个字符的话就需要检查那个码元的值然后根据码元的类型(是否具有代理标志位)决定是否还需要向前或向后检查一个相邻的码元的值(可以不必理会除了前后相邻的两个码元之外的其他码元)。
由于引导代理、尾随代理、BMP字符码元三者互不重叠搜索就很简单这意味着UTF-16具有“自同步”(self-synchronizing)性通过仅检查一个码元就可以判断当前字符的下一个字符的起始码元每个字符码元的边界很明确同时还具有“非传递”性单独的一个UTF-16码元出错涉及的只是一个字符不会传递到文本的其他部分去因此即使文本中某些字符数据遭到破坏其影响也只是局部性的。
UTF-8也有类似优点。但许多早期的编码方式就不是自同步的比如大多数的多字节编码标准如GBK、Big5等必须从头开始分析文本才能确定不同字符的码元的边界也不具有非传递性局部字符数据被破坏很可能传递到整个文件导致整个文件无法正确显示。
因此UTF-8和UTF-16编码方式所具有的“自同步性”、“非传递性”等特点除了增强抗干扰能力外也提供了随机访问的能力。
11.
由于在大多数的文本数据中代理对(即增补平面字符码元序列)出现的概率是很小的很多情况下处理的还是非代理对(即基本平面字符码元序列)导致许多软件处理代理对的部分往往得不到充分的测试。这导致了一些长期的bug与潜在安全漏洞甚至有些广为流行、得到良好评价的优秀软件也是如此。
因此虽然编程时同时考虑文本中可能出现的不同存储长度的字符(基本平面字符是单16位编码即单码元编码增补平面字符是双16位编码即双码元编码)并相应做出不同的处理会比单纯只考虑16位编码在性能上要逊色一些。但实际上现有的遵循定长16位编码规范但不能处理代理对的程序只需做很小的一点修改就可以同时处理基本平面字符和增补平面字符的编码了。
另外需要特别注意的是虽然Unicode标准规定BMP代理区(UD800~UDFFF)的码点值不对应于任何字符即未作定义但在UCS-2中UD800~UDFFF是被定义了的也就是已经用于某些字符了。不过只要前后两个16位码元不是恰好构成了代理对许多程序还是能把这些不匹配Unicode标准的字符码元正确地辨识、转换成合规的码元。这种由历史原因造成的码元序列按现在的Unicode标准来看应算作是编码错误。
笨笨阿林原创文章转载请注明出处 未完待续