欢迎各位兄弟 发布技术文章
这里的技术是共享的
码位:
GB18030是多字节字符集,它的字符可以用一个、两个或四个字节表示。GB18030的码位定义如下:
字节数 码位空间 码位数 字符数 单字节 0x00~0x7F 128 128 双字节 0x8140~0xFE7E和0x8180~0xFEFE 23940 21897 四字节 0x81308130~0xFE39FE39 1587600 54531
GB18030有128+23940+1587600=1611668个码位。Unicode的码位数目是0x110000(1114112),少于GB18030。所以,GB18030有足够的空间映射Unicode的所有码位。
GB18030的1611668个码位目前定义了128+21897+54531=76556个字符。Unicode 5.0定义了99089个字符。
GB18030编码可以分为:单字节部分、双字节部分和四字节部分。单字节部分与Unicode的0x00-0x7f完全相同。双字节部分与GBK有两点差异:
Unicode的BMP一共有65536个码位。其中代理区(0xD800-0xDFFF)有2048个码位,这2048个码位是不能定义字符的。GB18030的单字节部分映射了128个码位,GB18030的双字节部分映射了23940个码位。还剩下65536-2048-128-23940=39420个码位。
GB18030将这39420个码位顺序映射到从0x81308130开始的码位空间。GB18030将Unicode的16个辅助平面(0x10000-0x10FFFF,一共1048576个码位)顺序映射到从0x90308130开始的码位空间。GB18030四字节部分中只有这两个区域定义了字符,其它空间都是保留区和自定义区。本文的第3节和第4节还会详细讨论GB18030的双字节和四字节部分。
GB18030的设计思路可以概括到以下几点:
在GB18030目前定义的76556个字符中,只有24个字符被定义到Unicode的PUA区。这24个字符包括1区的10个竖排标点符号(0xA6D9-0xA6DF、0xA6EC-0xA6ED和0xA6F3)和4区的14个汉字(0xFE51、0xFE52、0xFE53、0xFE59、0xFE61、0xFE66、0xFE67、0xFE6C、0xFE6D、0xFE76、0xFE7E、0xFE90、0xFE91、0xFEA0)。4区的14个汉字在Unicode 5.0中其实也可以找到非PUA的编码,详见《Unicode、GB2312、GBK和GB18030中的汉字》。但按照GB18030,它们还是应该映射到PUA码位。
GB18030-2000和GB18030-2005的区别及以后版本
GB18030-2005与GB18030-2000的编码体系结构是完全相同的。GB18030-2005相对于GB18030-2000主要有以下变化:
其中 的编码调整比较有意思。 的GB18030编码是0xA8BC, 在Unicode 5.0的编码是0x1E3F。在GB18030-2000中0xA8BC被映射到Unicode的0xE7C7,因为双字节部分没有映射0x1E3F,所以它作为BMP的未映射字符被放到四字节部分的0x8135F437。GB18030-2005将0xA8BC映射到0x1E3F,那么Unicode码位0xE7C7怎么办呢?为了最小化对原来编码的影响,设计者将Unicode码位0xE7C7映射到本来映射0x1E3F的0x8135F437。
GB18030已经映射了Unicode的所有码位,所以不管Unicode怎么变化,GB18030不过就是在现在的码位上增加一些字形而已,编码不会变化。只有现在还映射到PUA的24个字符以后可能会调整到非PUA码位。调整方法应该与 的调整方法相同。
GB18030双字节部分
前面已经介绍过GB18030双字节部分与GBK的区别,本小节再提一些细节。前面也说过,GB18030映射了Unicode除代理区外的所有码位。所以,Unicode BMP的6400个PUA码位在GB18030中都有对应的码位。GB18030双字节部分映射了2067个PUA码位。
前面说过,GBK映射了2149个PUA码位。现在GB18030双字节部分映射了2067个PUA码位。所以有2149-2067=82个字符的映射发生了变化。GBK原来有95个字符映射到PUA,其中81个字符在GB18030中被映射到非PUA码位。余下的14个汉字就是《Unicode、GB2312、GBK和GB18030中的汉字》提到的那14个汉字(0xFE51、0xFE52、0xFE53、0xFE59、0xFE61、0xFE66、0xFE67、0xFE6C、0xFE6D、0xFE76、0xFE7E、0xFE90、0xFE91、0xFEA0)。附件1列出了这些字符的编码变化。82个映射变化的码位,除了这81个外,还有一个就是欧元符号:GB18030编码是0xA2E3,Unicode编码是0x20AC。码位0xA2E3在GBK中被映射到0xE76C,GBK的码位0xA2E3没有定义字符。
GB18030双字节部分与Unicode的映射没有规律,只能通过查表方法映射。
GB18030四字节部分
GB18030四字节部分的字符可以见GB18030-2005的“表3 四字节部分的码位安排”,一共54531个字符。GB18030四字节部分的码位可以见GB18030-2005的“7.3 四字节部分字符的排列顺序”。其中定义字符的只有两个区域:
为了叙述方便,本文将0x81308130~0x8439FE39称作“BMP扩展部分”,将0x90308130~0xE339FE39称作“辅助平面部分”。GB18030四字节部分的码位空间是0x81308130~0xFE39FE39。第二字节有(0x39-0x30+1)=10个可能值。第三字节有(0xFE-0x81+1)=126个可能值。第四字节也是(0x39-0x30+1)=10个可能值。为了方便下面的演算,本文为这个码位空间定义几个名词:
四字节部分一共有(0xFE-0x81+1)=126个一级区。BMP扩展部分有4个一级区。辅助平面部分有84个一级区。还有38个一级区是保留区或自定义区。
BMP扩展部分
BMP扩展部分占据四字节部分开头的4个一级区,一共有4*12600=50400个码位。这段空间的Unicode映射说起来还是很简单的,就是顺序映射单字节、双字节没有映射过的BMP码位。这些映射关系在GB18030-2000中确定下来。以后的调整(例如 )只是个别字符,不会影响其它字符的位置。但是因为双字节字符已经映射过的BMP码位没有什么规律,所以造成BMP扩展部分的Unicode映射也不能用公式换算,还是要查表解决。
显然这50400个码位中只用到了39420个码位,其余码位都是保留的。出于好玩,我们来计算一下最后一个非保留码位(0xFFFF)的位置,计算过程如下:
所以Unicode编码0xFFFF映射的GB18030码位是0x8431A439。在BMP扩展部分中,0x8431A439以后的码位都是保留码位。上述计算中,/表示整除(例如5/3=1),%表示取余(例如5%3=2)。
2.5.2 辅助平面部分
辅助平面部分用84个一级区(0x90308130~0xE339FE39)直接映射Unicode的16个辅助平面。这部分映射是可以直接用公式计算的。让我们看看怎么计算。
与Unicode的映射
附件3给出了GB18030和Unicode的映射表。这个Excel文件是在网友谢振斌先生的映射表基础上制作的,包含3张表格:
也可以从下面附表中的部分内容看出一些端倪
双字节部分
GB18030 Unicode Unicode GB18030 8140 4E02 00A4 A1E8 8141 4E04 00A7 A1EC 8142 4E05 00A8 A1A7 8143 4E06 00B0 A1E3 8144 4E0F 00B1 A1C0 8145 4E12 00B7 A1A4 8146 4E17 00D7 A1C1 8147 4E1F 00E0 A8A4
BMP扩展部分
GB18030 Unicode 81308130 0080 81308131 0081 81308132 0082 81308133 0083 81308134 0084 81308135 0085 81308136 0086 81308137 0087 81308138 0088 81308139 0089
辅助平面部分
第一字节 第二字节 第三字节 第四字节 Unicode编码 95 32 82 36 20000 9A 34 84 31 2FFFF
Unicode m1 n1 m2 n2 m3 n3 第一字节 第二字节 第三字节 第四字节 20000 5 2536 2 16 1 6 95 32 82 36 2FFFF 10 5071 31 3 1 9A 34 84 31