您的位置:首页 > 其它

国际编码与中文字符

2015-12-30 21:21 134 查看
Windows操作系统使用ASCII码对应各种字符,每个ASCII码对应一个Unicode码。ASCII码从\u0000到\u007F(0-127)共128个字符,英文字符均在其中,其二进制表示为0xxxx
xxxx,扩展128个字符为\u0080-\u00FF(128-255),二进制表示为1xxx xxxx。
Unicode又称UCS(UnicodeCharacter Set),是一种字符编码方法,由一个字节表示(0x00-0xff),其即对应ASCII码,如\u0041对应英文字符’A’,
Unicode为全世界通用编码,为了能够表示出两个字节的中文字符,采用了两个字节编码,称为UCS-2,而UCS还有采用四个字节编码的UCS-4。
UCS-2与GB2312编码类似,使用两组16进制的编码合成一个字符,如汉字”啊”的UCS-2码(一般直接称为Unicode)为
\u554A,以此类推,其他中文字符在Unicode中的编码亦用此种形式保存。UCS-4
为32位二进制表示,而实际上最高位必须为0,因此UCS-4可以表示2^31
个字符。UCS-4 的四个字节中根据最高字节分成2^7个group,每个group根据次高字节分为2^8个plane,每个panel根据次低字节分为2^8个rows,每个rows包含2^8个cells。而group和plane均为0的码称为BMP(Basic
Multilingual Plane),即是UCS-4中高两个字节为0的编码为BMP。目前UCS-4还未有分配在BMP范围之外的字符。
中文字符常用的编码为GB2312,是ASCII码的扩展。每个国家均从ASCII码进行了扩展,拥有自己独立的编码。GB2312共收容中文字符7445个,其中汉字字符其高位字节为B0-F7,低位字节为A1-FE,D7FA-D7FE范围为空字符,如汉字字符”啊”的GB编码为B0A1,共6768个。后扩展汉字编码为GBK,共收容中文字符21886个,再后来又扩展为GB18030,收容中文字符27484个。GB2312和GBk编码均用两个字符构成,ASCII码由一个字符构成,而GB18030包括单字节、双字节和四字节方式,四字节收录包括CJK(China、Japan、Korea)等的编码。

从ASCII—>GB2312—>GBK—>GB18030,其编码依次扩展并且向下兼容。所谓向下兼容,就是前一种编码字符的编码值在后面的编码相同,使用不同种编码对应字符的编码值一样,就是后面的编码范围比前一种大。GB2312和GBK使用两个字符,实现与单个字符的ASCII码兼容,就是在前面补上个0值字节,以使编码值相等。
GB还有一种码为GB13000.1,是ISO/IEC 10646-1的中文版。GB13000.1其实是GB2312的另一扩展,采用四字节编码,其扩充了六个辅助集,收容的GB2312编码称为基本集。其中第二、第四辅助集是简体汉字集,第一、第三、第五辅助集是繁体汉字集,第一辅助集又称GB12345,与GB2312
中的汉字一一对应,而第二与第三、第四与第五也是简繁体的对应。另外没有第六辅助集,而是有第七辅助集,收容的是在CJK统一使用的汉字部分,
中文字符也曾使用区位码,由两组十进制数字组成,高位组称为区,低位组称为位,区在1-9是中文字符(标点符号等),16-55为一级汉字区(汉字按拼音排序),56-87为二级汉字区(汉字按部首/笔画排序),由此组成的一个四位十进制的编码即为区位码。区位码与GB2312可以互相转换,由区位码转为GB2312方式为转化为16进制的区位码的区和位分别加上A0,由此得到的编码即是GB2312码,如中文字符”啊”的区位码为1601,转化为16进制为1001,10和01分别加上A0为B0A1,即是字符”啊”在GB2312上的编码。区位最高为94,10-15、88-94区未定义字符。
实际上,以上的编码方式只是用于存放字符,并不能用于各个地方的传输。传输使用的是另外一种编码——UTF(UCS Transformation Format)。UTF有UTF-8、UTF-16、UTF-32三种编码,8、16、32的区分实际上就是对于UTF以多少位为单元进行编码,UTF-8是以8位二进制即一个字节为单元,UTF-16以两个字节为单元,UTF-32以四个字节为单元,通过编码进行传输。
UTF-8的传输规则实际上是这样的:

        对于单字节的字符,字节码第一位为0,后7位为该字符的Unicode码,因此对于非扩展的ASCII码,其编码与UTF-8相同。
对于n个字节(n>1)的字符,字节码的第一个字节前n位为1,n+1位为0,后面字节前两位为10,其余位为该字符的Unicode码。
              UCS-2与UTF-8的具体传输规则如下(左UCS-2
右UTF-8):

                   0000– 007F—> 0xxx xxxx
                                            1字节

                   0080– 07FF—>110x xxxx 10xx xxxx                             
2字节

                   0800– FFFF—>1110 xxxx 10xx xxxx 10xx xxxx             
3字节

        依据以上规则就可以进行Unicode与UTF-8的转换。比如中文字符”啊”的Unicode码为\u554A,将其转换为二进制为0101
0101 0100 1010,根据其Unicode码所在区为0800 – FFFF,将二进制码依次从右往左代入x
得到 1110 0101 1001 0101 1000 1010 换为16进制码则为E5 95 8A,此3字节码即为中文字符”啊”的UTF-8码。

中文字符为2字节,而在进行中文输入法时有些字符如空格” ”依然只占一个字节,或者需切换输入法来代替,因此在进行某些中文字符串操作时对该字符应该采用两个相同的1字节字符代替。如数据库进行查询操作时的查询某个表中第二个字为”啊”的内容:
           SELECT value FROM tabel WHERE LIKE ‘__啊%’;
此中用了两个单字节的'_'来表示一个中文字符即是如此。
         还有个小知识,编码的存储方式有两种,分别为Big Endian和Little Endian。此两种存储方式的区别在于,对于双字节的编码,其两组16进制码是谁前谁后问题,按照编码方式正序存储,则为Big
Endian,反序存储则为Little Endian。例如中文字符”啊”,其Unicode码为554A,如果采用Big
Endian存储则55在前,4A在后,如果采用Little Endian存储,则4A在前,55在后。因此在计算机中,对于读取文档又有问题了,计算机并不知道文档是采用哪种存储方式,因此在一般的文件如文本文档中,开头加入了个”ZERO
WIDTH NO-BREAK SPACE”的Unicode字符,其编码为FEFF,命名为”零宽度非换行空格”。而实际上Unicode在FFFE上并没有字符,因此计算机则可以根据这个对文档进行编码方式识别,如果读取到FEFF,则为Big
Endian,读到FFFE则为Little Endian。

三种编码GB、Unicode和UTF,Unicode与UTF的转换已经知道,GB要转换为UTF,实际上是经过先转换为Unicode再转为UTF。GB转为Unicode,没有什么规律,是按GB与Unicode的映射表来转换,计算机对其的转换也是通过其映射来转换,由此将GB转化为UTF码。
Windows系统内核支持Unicode字符集,从而支持全世界的所有语言文字,而Windows内码为code page(代码页),通过使用代码页来适应各个国家和地区。代码页只支持单字节和双字节编码。代码页包括了各个国家地区的语言,由此适应该地区的编码。如中文(简体,中国)对应的编码为GB编码,在文本文档的另存为中有个编码格式为ANSI,其即指定编码存储格式为缺省(Default)编码,根据计算机系统的控制面板下的区域和语言选择格式而定。
有时候当你打开一个文本文档,你会发现里面内容全是乱码,其原理即是:写文档的时候使用了缺省编码ANSI,根据地区环境编码,而当你打开时文本读取ANSI缺省为你的区域,两个不同区域编码的不兼容,造成读出来的内容全是乱码。由此建议写文档时或者编程人员在编程时应在各种高级语言IDE编程环境下设为国际通用的UTF-8或Unicode码,由此进行文件/代码迁移时就不会发生乱码现象了。
到此为止,对中文字符的排序有个想法,如果有哪种编码是按拼音排序,则可采用获得编码的方式对一串字符串进行排序。根据测试结果,中文字符的Unicode码并不是按拼音排序,而是像根据部首来排序,因此,并不能根据Unicode码排拼音序。前面说过,中文字符区位码一级汉字区为按拼音排序,而区位码实际上通过分别加上A0的操作成为GB2312编码,根据兼容原理,GB的排序规则也是按照拼音排序,并且通过测试结果确实如此,因此通过GB转化为Unicode转化为UTF,则就实现了中文字符的排序规则。如在java里,字符串String的getBytes(Charset
charset)方法可以得到字符串的字节数组,通过取8位二进制(&0xFF)得到指定组的16进制编码。排序方法:通过实现Comparable接口,然后通过String.getBytes(“GBK”)得到byte数组,经过一系列的转换对byte数组值进行比较就可以实现排序了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编码