多种编码的基本转换(收集)

好久没有来锄草了,最近遇到编码问题,记录一下

 

主要包括区位码,GB,GB2312,UNICODE,UTF-8,ISO8859-1。大部分为转载,如有错误,请高人指正。

 

GB2312和ISO8859-1无法直接转换,这个问题头疼,不过网上还是有解决方案的,如果是这个问题,大家就狗狗一下吧。

 

以下内容主要来自:http://www.mao2.com/papers/zhongwenbianma.html

http://hi.baidu.com/cuifenghui/blog/item/735b55da1804a1dfb7fd4817.html

 

1.区位码: 

我国国家标准汉字信息交换用编码,全称《信息交换用汉字编码字符集基本集》,标准号为 GB 2312-80(GB 是“国标”二字的汉语拼音缩写),由中华人民共和国国家标准总局发布,1981年5月1日实施,新加坡等地也使用这一编码。区位码是一个四位的十进制数,它的前两位叫做区码,后两位叫做位码。区位码的编码范围是:0101~9494。比如,按拼音排序后的第一个汉字是“啊”,它的区位码为1601(十六进制为1001 H)。下图是新华字典所显示的汉字“啊”的信息。

 

2. 汉字国标码(GB):

又称交换码,是一个码集。将区位码的十进制行列值转换成16进制,再分别加上20H得到。举例:将“万”的区位码转换为16进制表示:2D 52,分别加上20H得:4D 72,即为国标码。
由此,汉字第一个字节的最小值:10H + 20H =30H, 最大值:57H + 20H = 77H
第二个字节最小值: 01H + 20H = 21H, 最大值: 5EH + 20H = 7EH

 

3.GB2312 码:

又称为国标码,在区位码的基础上,分别将区号值和位号值各加 32(20H)而得到,于是它的编码范围是2121H~7E7EH,于是“啊”的GB2312 的编码为3021 H(即1001H+2020H)。但是,因为GB2312 与ASCII有重叠,通行方法是将GB2312 码两个字节的最高位置1以示区别,编码范围变为 0A1A1H~0FEFEH(实际只用到0xF7FEH)。这种在第八位置"1",提示计算机转入双字节的编码方式也叫EUC(Extended UNIX Code)编码,所以“啊”的GB2312 的最终编码为B0A1 H(即3021 H+8080H)。其实GB2312 和区位码是一样的,应该合在一起谈。但事实上两个的编码又不一样,我也不知为什么要弄得如此复杂。或许可以这样理解:区位码是一个编码方案,而 GB2312 编码则是这个方案在计算机里的一个具体实现。GB2312 将收录的汉字分成两级:第一级是常用汉字计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于 56-87区,按部首/笔画顺序排列。共计6763个汉字。

 

GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。GB2312-80中共收录了7545个字符,用两个字节编码一个字符。每个字符最高位为0。GB2312-80编码简称国标码。

  GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。

 

4. UNICODE

Unicode字符集(简称为UCS),国际标准组织于1984年4月成立ISO/IECJTC1/SC2/WG2工作组,针对各国文字、符号进行统一性编码。1991年美国跨国公司成立UnicodeConsortium,并于1991年10月与WG2达成协议,采用同一编码字集。目前Unicode是采用16位编码体系,其字符集内容与ISO10646的BMP(BasicMultilingual Plane)相同。Unicode于1992年6月通过DIS(DrafInternationalStandard),目前版本V2.0于1996公布,内容包含符号6811个,汉字20902个,韩文拼音11172个,造字区6400个,保留20249个,共计65534个。Unicode编码后的大小是一样的.例如一个英文字母"a" 和 一个汉字"好",编码后都是占用的空间大小是一样的,都是两个字节!

Unicode可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容iso8859-1编码的,也不兼容任何编码。不过,相对于iso8859-1编码来说,uniocode编码只是在前面增加了一个0字节,比如字母'a'为"0061"。
需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode编码来处理的,比如java。

 

随着国际互联网的迅速发展,要求进行数据交换的需求越来越大,不同的编码体系越来越成为信息交换的障碍,而且多种语言共存的文档不断增多,单靠代码页已很难解决这些问题,于是UNICODE应运而生。

UNICODE 通常用作涉及双字节字符编码方案的通用术语。UNICODE CCS 3.1(CCS:编码字符集,coded character set) 的官方称谓是 ISO10646-1 通用多八字节编码字符集(Universal Multiple Octet Coded Character Set,UCS)。

UNICODE 编码系统可分为编码方式和实现方式两个层次。

目前用于实用的 UNICODE 版本的编码方式使用16位的编码空间,也就是每个字符占用2个字节。这样理论上一共最多可以表示 65536 个字符,基本满足各种语言的使用。标准的UNICODE编码方案使用32位的的编码空间,目前编码范围是0到10FFFF H。例如“啊”的UNICODE编码为55 4A H。

UNICODE 的实现方式不同于编码方式。一个字符的 UNICODE 编码是确定的。但是在实际传输过程中,由于不同系统平台对非ASCII码的处理都不太一致,以及出于节省空间的目的,对 UNICODE 编码的实现有着不同的方式。UNICODE 的实现方式称为UNICODE转换格式(UNICODE Translation Format,简称为 UTF)。常用的有:

1)UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-6 byte。其与UNICODE编码的关系如下:

U-00000000-U-0000007F: 0xxxxxxx
U-00000080-U-000007FF: 110xxxxx 10xxxxxx
U-00000800-U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
4-6位的UTF-8编码对应着U-00010000-U-7FFFFFFF,比较少用到,就不列出了。
“啊”的UTF-8编码是E5 95 8A,占3字节。

2)UTF-16,16位编码,基本上就是UNICODE编码的实现。这里只能说是“基本上”,因为对于码值在10000H到10FFFFH之间的 UNICODE码,UTF-16是使用“代理对”(即两个UNICODE码)来实现编码的。幸好,我们常用的字符,包括各国的文字、符号等,都可以使用单个UTF-16来编码,不需要通过代理对实现。因此,UTF-16是UNICODE编码实现的指定首选编码方式。例如“啊”的UTF-16编码是55 4A H,占2字节,并且与实际“啊”的实用16位UNICODE编码值是相等的。

3)UTF-32,32位编码,顾名思义,与标准UNICODE编码是一一对应的。例如“啊”的UTF-32编码是00 00 55 4A,占4字节。

上面罗列了一堆编码,希望大家还没有看晕过去。我们现在分析几种JAVA中的乱码问题。

首先,我们看看Window是如何处理文本文件的。Window2000内核是使用UNICODE编码进行字符处理的。Window上的纯文本编辑器(包括 JBuilder等JAVA开发工具的编辑器),在读进一个纯文本文件时,如果该文件本身没有指定编码格式,则编辑器会使用当前Window的代码页(中文Window下是CP936,即GBK)对文件内容字节流进行转换,转换成UNICODE编码。在保存时,则将内存中的UNICODE编码通过代码页转换为本地编码,以字节流形式存入磁盘。

JAVA核心也使用UNICODE进行字符处理,与Window2000是一致的,因此,处理文件的过程也和上面是一样的。因为internet传输也是以字节流方式传输的,因此JAVA在处理网络字节流时也按上述方式进行。在这种byte->char->byte类型的转换中,如果中间出现编码转换错误,就会冒出中文乱码问题了。

案例一:JAVA产生的文件(或控制台输出),在Window下正常,上传到UNIX运行时乱码。这是因为两台机器的代码页不一致造成的。解决办法:将UNIX上的语言区域设为与Window的一致后,再运行JAVA程序。

案例二:文本文件使用Window文本编辑器可以正常打开,而JAVA应用程序读入该文件时乱码。原因是文本文件有多种的编码方式包括ASCII,UTF- 8,UTF-16(而CPU有着字节顺序的问题,故UTF-16又细分为UTF-16LE小尾序、UTF-16BE大尾序两种编码)。文本文件在缺省下是根据当前系统的区域选定的编码方式来保存的,Window下也就是代码页。解决办法:检查该文本文件的编码方式,并在JAVA程序中按该编码方式读取数据。

 

5. UTF-8

在上面已经讲述,其实是包含关系。

 

6. ISO8859-1:

属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列。比如,字母'a'的编码为0x61=97。

 

最常用的是ASCII编码,编码范围是00 H-7F H。ISO8859编码是对ASCII的扩展,扩展部分是80 H-FF H,用于定义其它非英文字母,如法语、德语等。其中ISO8859-1是最著名的一个,定义了西欧拉丁语符号。注意,ISO8859-1与GB18030 在编码上也是重叠的。


很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用iso8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然"中文"两个字不存在iso8859-1编码,以gb2312编码为例,应该是"d6d0cec4"两个字符,使用iso8859-1编码的时候则将它拆开为4个字节来表示:"d6d0 cec4"(事实上,在进行存储的时候,也是以字节为单位处理的)。而如果是UTF编码,则是6个字节"e4b8 ad e6 96 87"。很明显,这种表示方法还需要以另一种编码为基础。

 

 

中文汉字编码体系:

 

1.国家标准汉字代码体系
   汉字字数繁多,属性丰富,因而汉字代码体系也较复杂,包括:
   (1)汉字机内码。它们是汉字在计算机汉字系统内部的表示方法,是计算机汉字系统的基础代码。
   (2)汉字交换码。它们是国标汉字(如机内码)进行信息交换的代码标准。
   (3)汉字输入码。它们是在计算机标准键盘上输入汉字用到的各种代码体系。
   (4)汉字点阵码。它们是在计算机屏幕上显示和在打印机上打印输出汉字的代码体系。
   (5)汉字字形控制码。为了打印各种风格的字体和字形所制定的代码。
   这些代码系统有的必须有统一的国家标准,有的则不要求统一。近年来我国已经制定系列汉字信息处理方面的国家标准,今后将继续完善,并与国际上求得统一。

2. 国家标准汉字交换码
   我国制定了“中华人民共和国国家标准信息交换汉字编码”,标准代号为GB2312—80,这种编码又称为国标码。在国标码的字符集中共收录了一级汉字3755个,二级汉字3008个,图形符号682个,三项字符总计7445个。
   在国标GD2312—80中规定,所有的国标汉字及符号分配在一个94行、94列的方阵中,方阵的每一行称为一个“区”,编号为01区到94区,每一列称为一个“位”,编号为01位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的“区位码”。区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的区位码。汉字“母”字的区位码是3624,表明它在方阵的36区24位,问号“?”的区位码为0331,则它在03区3l位。
   所有的汉字和符号所在的区分为以下四个组:
(1)01区到15区。图形符号区,其中01区到09区为标准符号区,10区到15区为自定义符号区。
   01区到09区的具体内容如下;
   1)01区。一般符号202个,如间隔符、标点、运算符、单位符号及制表符;
   2)02区。序号60个,如1.~20.、(1)~(20)、①~⑩及(一)~(十);
   3)03区。数字22个,如0—9及X一XII,英文字母52个,其中大写A—Z、小写a—z各26个;
   4)04区。日文平假名83个;
   5)05区。日文片假名86个;
   6)06区。希腊字母48个;
   7)07区。俄文字母66个;
   8)08区。汉语拼音符号a—z26个;
   9)09区。汉语拼音字母37个。
(2)16区到55区。一级常用汉字区,包括了3755个一统汉字。这40个区中的汉字是按汉语拼音排序的,同音字按笔划顺序排序。其中55区的90一94位未定义汉字。
(3)56区到87区。二级汉字区,包括了3008个二级汉字,按部首排序。
(4)88区到94区。自定义汉字区。
第10区到第15区的自定义符号区和第88区到第94区的自定义汉字区可由用户自行定义国标码中未定义的符号和汉字。

3. 国家标准汉字机内码
汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上所述,汉字区位码的区码和位码的取值均在1~94之间,如直接用区位码作为机内码,就会与基本ASCII码混淆。为了避免机内码与基本ASCII码的冲突,需要避开基本ASCII码中的控制码(00H~1FH),还需与基本ASCII码中的字符相区别。为了实现这两点,可以先在区码和位码分别加上20H,在此基础上再加80H(此处“H”表示前两位数字为十六进制数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别   称为高位字节和低位字节,这两位字节的机内码按如下规则表示:
高位字节=区码+20H+80H(或区码+A0H)
低位字节=位码+20H+80H(或位码+AOH)
由于汉字的区码与位码的取值范围的十六进制数均为01H~5EH(即十进制的01~94),   所以汉字的高位字节与低位字节的取值范围则为A1H~FEH(即十进制的161~254)。
例如,汉字“啊”的区位码为1601,区码和位码分别用十六进制表示即为1001H,它的机内码的高位字节为B0H,低位字节为A1H,机内码就是B0A1H。  

4. 汉字的输入码
在计算机标准键盘上,汉字的输入和西文的输入有很大的不同。西文的输入,击一次键就直接输入了相应的字符或代码,“键入”和“输入”是同一个含义。但是在计算机上进行汉字输入时,“键入”是指击键的动作即键盘操作的过程,而“输入”则是把所需的汉字或字符送到指定的地方,是键盘操作的目的。目前已有多种汉字输入方法,因此就有多种汉字输入码。汉字输入码是面向输入者的,使用不同的输入码其操作过程不同,但是得到的结果是一样的。不管采用何种输入方法,所有输入的汉字都以机内码的形式存储在介质中,而在进行汉字传输时,又都以交换码的形式发送和接收。
国标GB2312—80规定的区位码和沿用多年的电报码都可以作为输入码。这类汉字编码和输入码是一一对应的,具有标准的性质,它们编码用的字符是10个阿拉伯数字,每个汉字的码长均为等长的四个数码。
其他编码的种类很多,可从以下几点加以讨论:
(2)编码类型。可分为拼音码、字形码、音形结合码等类型。
(2)编码规则。不同的编码方案有很大的不同,有的规则简单,学习起来较容易记忆,‘有的规则复杂,较难记亿。
(3)编码字符集。有用字母键的,有用数字键的,有用字母键加数字键的,或者用了更多的键作编码字符集的。
(4)编码长度。它与编码字符集的大小有关,字符集越大,编码长度越短。采用26   个字母的编码,其码长一般为四位。
(5)对应关系。除上面提到的区位码和电报码为一一对应的无重码编码外,其他现有的编码方案均有一定数量的重码。所谓重码即一码对应多字。有许多编码为了增加输入的灵活性,同一汉字用多个码来对应,例如双音编码。
(6)单宁和词汇的编码。现有的编码方案,为了提高效率,除了单字外还规定了词汇的编码,甚至使用者可以自行增加词汇库中的词汇,但在提高效率的同时也增加了记亿和操作的复杂性。
(7)码表的类型和大小。从汉字输入码到机内码的转换一股需要在机内检索码表。如果输入码和机内码存在简单的函数关系,有公式可以计算,如区位码等编码就不需要码表,其他没有简单函数关系的编码就需要码表。码表大小与数据结构、单字数量、词汇数量等因素有关。国标血2312—80规定的6763个一、二级汉字,备类编码的码表从几千字节到几万字节。随着词汇旦的增加,有的码表达到了若干兆字节。

5. 汉字的点阵码
汉字的显示和输出,普遍采用点阵方法。由于汉字数量多且字形变化大,对不同字形汉字的输出,就有不同的点阵字形。所谓汉字的点阵码,就是汉字点阵字形的代码。存储在介质中的全部汉字的点阵码又称为字库。 .
   16x16点阵的汉字其点阵有16行,每一行上有16个点。如果每一个点用一个二进制位来表示,则每一行有16个二进制位,需用两个字节来存放每一行上的16个点,并且规定其点阵中二进制位0为白点,1为黑点,这样一个16X16点阵的汉字需要用2×t6即32个字节来存放。依次类推,24×24点阵和32×32点阵的汉字则依次要用72个字节和128个字节存放一个汉字,构成它在字库中的字模信息。
要显示或打印输出一个汉字时,计算机汉字系统根据该汉字的机内码找出其字模信息在字库中的位置,再取出其字模信息作为字形在屏幕上显示或在打印机上打印输出。

你可能感兴趣的:(多种编码的基本转换(收集))