unicode和ISO 8859-1

来源:互联网 发布:中标麒麟软件 编辑:程序博客网 时间:2024/05/03 23:55

最初的unicode编码是固定长度的,16位,也就是2两个字节代表一个字符,这样一共可以表示65536个字符。显然,这样要表示各种语言中所有的字符是远远不够的。Unicode4.0规范考虑到了这种情况,定义了一组附加字符编码,附加字符编码采用2个16位来表示,这样最多可以定义1048576个附加字符,目前unicode4.0只定义了45960个附加字符。

Unicode只是一个编码规范,目前实际实现的unicode编码只要有三种:UTF-8,UCS-2和UTF-16,三种unicode字符集之间可以按照规范进行转换。

 

UTF-8

UTF-8是一种8位的unicode字符集,编码长度是可变的,并且是ASCII字符集的严格超集,也就是说ASCII中每个字符的编码在UTF-8中是完全一样的。UTF-8字符集中,一个字符可能是1个字节,2个字节,3个字节或者4个字节长。一般来说,欧洲的字母字符长度为1到2个字节,而亚洲的大部分字符则是3个字节,附加字符为4个字节长。

Unix平台中普遍支持UTF-8字符集,HTML和大多数浏览器也支持UTF-8,而window和java则支持UCS-2。

UTF-8的主要优点:

  • 对于欧洲字母字符需要较少的存储空间。
  • 容易从ASCII字符集向UTF-8迁移。

UCS-2

UCS-2是固定长度为16位的unicode字符集。每个字符都是2个字节,UCS-2只支持unicode3.0,所以不支持附加字符。

UCS-2的优点:

  • 对于亚洲字符的存储空间需求比UTF-8少,因为每个字符都是2个字节。
  • 处理字符的速度比UTF-8更快,因为是固定长度编码的。
  • 对于windows和java的支持更好。

UTF-16

UTF-16也是一种16位编码的字符集。实际上,UTF-16就是UCS-2加上附加字符的支持,也就是符合unicode4.0规范的UCS-2。所以UTF-16是UCS-2的严格超集。

UTF-16中的字符,要么是2个字节,要么是4个字节表示的。UTF-16主要在windows2000以上版本使用。

UTF-16相对UTF-8的优点,和UCS-2是一致的。

Oracle从7.0开始提供对Unicode的支持。Oracle个版本的unicode字符集支主要有:

AL32UTF8

一种UTF-8编码的字符集,支持最新的unicode4.0标准。字符长度为1,2或者3个字节,附加字符则为4字节长。

UTF8

支持unicode3.0的UTF-8编码方式。由于附加字符是在unicode3.1中提出的,UTF8不支持附加字符。但是unicode3.0已经为附加字符预留了编码空间,所以即使在UTF8的数据库中插入附加字符,也是可以的,只是数据库会将该字符分隔成两部分,需要占6个字符的长度。所以,如果需要支持附加字符,那么建议将数据库的字符集切换为新的AL32UTF8。

UTF8可用于数据库字符集,也可用于国家字符集。

UTFE

UTFE是基于EBCDIC平台的unicode字符集,就像ASCII平台上的UTF8一样。不同的是,UTFE中,每个字符可能占1,2,3或者4个字节,而附加字符则需要2个4个字节,也就是8个字节来表示。

AL16UTF16

AL16UTF16是一种UTF-16编码的unicode字符集,在Oracle中用于国家字符集。

AL24UTFFSS

该字符集只支持unicode1.1规范,在Oracle7.2~8i版本中使用,目前已经淘汰。

 

我们经常会遇到编码问题。Java号称国际化的语言,是因为它的class文件采用UTF-8,而JVM运行时使用UTF-16(至于为什么JVM中要采用UTF-16,我没看过 相关的资料,但我猜可能是因为JAVA里面一个字符(char)就是16位的,而UTF-16正是双字节编码),都是unicode的编码。

unicode 的目标就是能支持世界上所有的字符集,也就是说几乎所有的字符集包含的字符在unicode中都有对应的编码。在unicode中,字符与代码的映射关 系,就是unicode字符集,称为UCS(Unicode Character Set),每个unicode字符编码称为code point(代码点?)。UTF-8和UTF-16是不同的UCS编码方法,UTF就是UCS Transformation Format。;

在Java 中,String的getBytes()方法就是对特定的字符串(unicode)按照给定的字符集进行编码(encode),new String()则可以按照某个字符集将字节流转换回unicode(decode)。Java里面的每一个String都是unicode编码。

再来看页面,如果不做特殊处理,Form的提交就按照页面的ContentType设置中的字符集进行编码转换,发送到后台,后台必须利用req.setCharacterEncoding来指定参数的编码格式(不同的应用服务器应有不同的指定方式),才能正确解码。

Java 里面的encode和decode都是相对于unicode而言的,encode的意思是将char[] --> XXX Encoding byte[],decode就是由XXX Encoding byte[] --> char[]。平常,当我们说“将GBK编码转换为UTF-8编码”的时候,实际的意思就是:GBK Encoding byte[] --> UTF-8 Encoding byte[],这种转换只有在需要用byte[]传输数据的时候才有意义,否则便是毫无意义的。

首先要说明的一点是:Java中的String对象就是一个unicode编码的字符串。

但是,我们通常会听到有人说:“我们需要将String由ISO-8859-1转换为GBK编码”,这又是怎么回事呢?实际上,我们并不是要“将 一个由ISO-8859-1编码的String转换为GBK编码的String”,反复说明的是,JAVA中的String都是unicode编码的,所以不存在“ISO- 8859-1编码的String”或“GBK编码的String”这样的说法。而需要转换的唯一的原因是String进行了错误的编码。我们经常会碰到由ISO-8859- 1转换为诸如GBK/UTF-8等等这样的需求。所谓的转换过程是:String --> byte[] -->String。
也许 你非常清楚这个过程的代码:new String(text.getBytes("ISO-8859-1"),"GBK")。但是,要真正理解起来并不是那么简单。表面上看似乎很容易理解, 不就是将text String对象按照ISO-8859-1的方式编码为byte[]然后再把它按照GBK的方式转换为String吗?但是这句代码很容易会被误解为: “将text String由ISO-8859-1转换为GBK编码”,这种说法是错误的。难道你见过用这样的代码:new String(text.getBytes("GBK"),"UTF-8")来对String进行编码转换的吗?

之所以你会经常看到new String(text.getBytes("ISO-8859-1"),"GBK")这句代码,是因为一个GBK的字节流被错误地以ISO-8859- 1的方式转换为String(unicode)了!发生这种情况最普遍的地方是一个GBK编码的网页向后台提交数据的时候,就有可能会看到这句代码的出 现。GBK的流被错误的当成ISO8859-1的流,所以便得到了一个错误的String。由于ISO8859-1是单字节编码,所以每个字节被按照原样 转换为String,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来!所以那句经典的new String(text.getBytes("ISO-8859-1"),"GBK")便出现了。

如果系统误以为是其它编码格式,就有可能再也转换不回来了,因为编码转换并不是负负得正那么简单的

ISO/IEC 8859-1

维基百科,自由的百科全书

ISO 8859-1,正式编号为ISO/IEC 8859-1:1998,又称Latin-1或“西欧语言”,是国际标准化组织内ISO/IEC 8859的第一个8位字符集。它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用附加符号的拉丁字母语言使用。曾推出过 ISO 8859-1:1987 版。

此字符集支援部分于欧洲使用的语言,包括阿尔巴尼亚语、巴斯克语、布列塔尼语、加泰罗尼亚语、丹麦语、荷兰语、法罗语、弗里西语、加利西亚语、德语、格陵兰语、冰岛语、爱尔兰盖尔语、意大利语、拉丁语、卢森堡语、挪威语、葡萄牙语、里托罗曼斯语、苏格兰盖尔语、西班牙语及瑞典语。

英语虽然没有重音字母,但仍会标明为ISO/IEC 8859-1编码。除此之外,欧洲以外的部分语言,如南非荷兰语、斯瓦希里语、印尼语及马来语、菲律宾他加洛语等也可使用ISO/IEC 8859-1编码。

法语及芬兰语本来也使用ISO/IEC 8859-1来表示。但因它没有法语使用的 œ、Œ、 Ÿ 三个字母及芬兰语使用的 Š、š、Ž、ž ,故于1998年被ISO/IEC 8859-15所取代。(ISO 8859-15同时加入了欧元符号)

0 0