一、Unicode编码介绍
1、ASCII码的不足
对于英文来说,ASCII码用0-127就足以代码所有字符,对于中文而言,则必须使用两个字节(Bytes)来代表一个字符,且第一个字节必须大于127。用两个字节来表示一个中文的方式,在习惯上称为双字节(即DBCS: Double-Byte Character Set),而相对之下,英文的字符码就称为单字节SBCS(Single-Byte Character Set)。
虽然双字节(DBCS)足以解决中英文字符混合使用情况,但对于不同字符系统而言,无论哪一种字符集都没有足够的字符来处理多种语言。大多数国家的字符集是以ASCII码为基础的编码集,就像英语和法语可以用同一个字符集来存储,但是例如德语和中文,俄语和韩语,甚至是繁体中文和简体中文都不能存储在同一个字符集中。事实上,字符集之间还有许多潜在的冲突,因为同样的数字码值可能代表不同的字符,或者同样的字符可能被不同的数字码值所表示。因此,ASCII码与其他国家字符集的问题在于它们不具有普遍性,必须经过字符码转换。
2、Unicode产生
为了解决以上问题,国际标准组织于1984年4月成立ISO/IEC JTC1/SC2/WG2工作组。针对各国文字、符号进行统一性编码。1991年美国跨国公司成立Unicode Consortium,并于1991年10月与WG2达成协议,采用同一编码字集。Unicode于1992年6月通过DIS(Draf International Standard)。目前版本V2.0于1996公布。内容包含符号6811个。汉字20902个。韩文拼音11172个。造字区6400个。保留 20249个。共计65534个。
UNICODE使任何语言的字符都可以为机器更容易的接受,UNICODE由 UC(UNICODE协会)管理并接受其技术上的修改。包括JAVA、LDAP、XML这样的技术标准中均要求得到UNICODE的支持。UNICODE 的字符被成为代码点(CODE POINTS),用U后面加上XXXX来表示,其中,X为16进制的字符。
UNICODE有双重含义。首先UNICODE是对国际标准 ISO/IEC10646编码的一种称谓(ISO/IEC10646是一个国际标准。亦称大字符集。它是ISO于1993年颁布的一项重要国际标准。其宗 旨是全球所有文种统一编码)。另外它又是由美国的HP、Microsoft、IBM、Apple等大企业组成的联盟集团的名称。成立该集团的宗旨就是要推 进多文种的统一编码。
UNICODE同现在流行的代码页最显著不同点在于:UNICODE是两字节的全编码。对于ASCII字符它也使用两字节表示。代码页是通过高字节的取值范围来确定是ASCII字符。还是汉字的高字节。如果发生数据损坏,某处内容破坏,则会引起其后汉字的混乱。UNICODE则一律使用两个字节表示一个字符。最明显的好处是它简化了汉字的处理过程。
UNICODE使用平面来描述编码空间。每个平面分为256行。256列。相对于两字节编码的高低两个字节。其字符集内容与 ISO10646的BMP(Basic Multilingual Plane,基本多文种平面)相同。
Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。 但这还不够。它不能覆盖全部历史上的文字。也不能解决传输的问题(implantation head-ache's)。尤其在那些基于网络的应用中。因此,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中。字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的最大好处。是UTF-8保留 了ASCII字符的编码做为它的一部分。例如。在UTF-8和ASCII中,“A”的编码都是0x41。UTF-16和UTF-32分别是Unicode 的16位和32位编码方式。考虑到最初的目的,通常说的Unicode就是指UTF-16。
3、Unicode的三种常用的编码格式:
l UTF-8:
UTF-8是Unicode的8-bit编码格式。是一个可变长的编码,并且是7-bit ASCII码的严格超集。严格超集的意思是7-bit ASCII码的每一个字符在UTF-8中均以相同的值表示。例如:在UTF-8和ASCII中,“A”的编码都是0x41。这种编码方式中,一个Unicode字符可以是1Bytes,2Bytes,3Bytes或者4Bytes。欧系语言字符用1Bytes或2Bytes表示,大部分亚系语言字符用3Bytes表示,一些补充字符用4Bytes表示。
UTF-8做为一种Unicode编码,应用于UNIX平台,HTML和大多数的Internet浏览器。UTF-8主要的优点有:
Ø 对于欧系语言能够更好的压缩存储。由于UTF-8是7-bit ASCII码的严格超
集,普遍欧系数据会占用更少的存储空间。
Ø 便于移植。UTF-8中对于7-bit ASCII码的存储值是相同的,所以在基于ASCII
码和UTF-8字符集的数据转换效率明显提高。
l UCS-2:
UCS-2编码是Unicode的16-bit混合编码,每一个字符占用2Bytes,与语系语言无关。UCS-2应用与Java和Windows NT 4.0。UCS-2仅支持Unicode字符集的3.0标准,不支持补充的字符。
UCS-2主要的优点有:
Ø 对于亚系语言能够更好的压缩存储,因为每一个字符都用2Bytes表示。
Ø 由于所有的字符都是等长表示,所以对字符串的处理更快。
Ø 更适合于Java和Microsoft的客户端。
l UTF-16:
UTF-16是16-bit编码的Unicode。UTF-16是基于UCS-2的一个扩展,提供对Unicode3.1标准中对补充字符的定义。一个Unicode字符可以用2Bytes或4Bytes表示。欧系语言的字符(包括ASCII码)和大部分的亚系语言是用2Bytes表示的。补充字符使用4Bytes表示的。UTF-16是微软公司Windows 2000,XP和2003操作系统的主要Unicode编码方式。
UTF-16主要的优点有:
Ø 存储亚系语言占用更少的空间。由于主要的亚系字符在UTF-16中用2Bytes表示,而同样的字符在UTF-8中要用3Bytes表示,所以UTF-16会节省硬盘和内存空间。
Ø 更加适合于Java和Microsoft客户端。
下图显示一些字符和它们依照UTF-8,UCS-2和UTF-16方式的编码:
字符 | UTF-8 | UCS-2 | UTF-16 | 解释 |
A | 41 | 0041 | 0041 | UTF-8中对于7-bit ASCII码 的存储值是相同的 |
c | 63 | 0063 | 0063 | |
Æ | C3 86 | 00C6 | 00C6 | 对于欧系字符 每一个字符都用2Bytes表示 |
ö | C3 B6 | 00F6 | 00F6 | |
亜 | E4 BA 9C | 4E9C | 4E9C | 对于亚系字符 UTF-8用3Bytes表示 |
| F0 9D 84 9E | N/A | D834 DD1E | 对于补充字符 UTF-8、UTF-16用4Bytes表示 无法用UCS-2表示 |
二、系统编码问题解决方案
1、问题描述
为实现地理空间数据一体化管理,即将地理空间要素的属性信息和空间信息统一存储于数据库中,需要将shapfile格式的数据导入到PostgreSQL中。在导入过程中,用欧系语言表示的数据均导入成功,而用亚系语言表示的数据则出现乱码。
2、问题分析
出现乱码可能是因为编码系统不统一而造成的,由于PostgreSQL中建立的数据库是UTF-8的编码格式,则shapefile格式的数据可能不是UTF-8编码格式。利用ESRI公司的ArcCatalog,将小流域的.shp数据通过Geodatabase格式转化成UTF-8编码的.shp文件,将该文件导入到数据库中,中文显示正常,则问题解决方案就是将所有涉及到中文数据的小流域.shp文件转化成UTF-8编码格式。用上述方法转化经过步骤很多,比较烦琐,遂通过修改程序代码来解决中文乱码问题。
3、问题解决
修改程序代码,将用来执行的sql语句转换成UTF-8编码格式,代码如下:
QCString querysql = query.utf8();
res = PQexec(conn, querysql);
其中,QString::uft8()返回字符串按照UTF-8编码的字符串。可见,用程序实
现编码的转换比较简单,经过转换的中文字符在导入数据库后,能够正常显示。这里需要说明的是:由于开发环境的字符编码是Unicode,所以在调试过程中,字符串的内容仍旧是乱码显示。如果数据库编码方式与开发环境编码方式相同,如均为Unicode,则可以用下面的代码实现调试内容的中文正确显示:
首先定义QTextCodec指针对象encoding:
QTextCodec *encoding;
初始化该对象,返回适合于本地的编码格式的QTextCodec的指针:
encoding = QTextCodec::codecForLocale();
将字符串query转换成本地编码格式:
QCString querysql = encoding->fromUnicode(query);
4、问题总结
由于编码格式的差异,经常造成中文的乱码问题,需要明确目的软件的编码格式,将源字符按照相应的编码格式,采取合适的方法进行转换,则能够简单清晰地解决中文乱码问题。