不少国际化应用的让我理解了这么一个道理:Unicode是为更方便的作国际化应用设计的,而Java核心的字符是基于UNICODE的,这一机制为应用提供了对中文“字”的控制(而不是字节)。但若是不仔细理解其中的规范,这种自由反而会成为累赘,从而致使更多的乱码问题
什么是编码页(code page)?
正如咱们所知,计算机只懂得数值。所以,当咱们想要它处理文本时,就把一门语言中每一个字符都赋以特定的值。简单地说来,这种字符与数值的对照表就叫编码页。在这种状况下,你可能常会听到诸如字符集(charset),字符表(charmap),编码(encoding),编码字符集(coded character set)等术语。虽然彼此间还有一些细微的差别,为理解的目的你能够认为它们都是指每种语言的字符、数值映射表。ASCII编码页就是一个很著名的例子,它把英文字母表和一些控制字符映射到一些特定的数值上去。
还有哪些编码页?围绕着编码页有哪些问题?
ASCII编码映射了127个字符,所以7位(bit)二进制数足够用来表示127个字符。程序则典型地在8位的缓冲区内处理文本。这在处理其它的语言的编码页是会出问题。例如日语这种语言,有成千让万个字符,8位二制只能表示256个不一样的字符,不可能惟一地表示每个日语字符。所以,人们用几个字节来表示一个日语字符。如今,咱们又遇到另外一个问题。缓冲区的字节数不等于缓冲区中的字符数。每个简单地字符串操做,都须要将字节组装成字符。
认识到这种复杂性,开发人员利用一种叫宽字符(wide-character)的技术来处理外语字符串。宽字符基本上是16位或32位的数据类型。容量够大,能知足亚洲语言的需求。处理字符串再也不使用8位的缓冲区(char *),而是使用16位的缓冲(unsigned short *)。所以每次移动指针,你均可以保证跳过了一个字符(而不是原先那多是半个)。
不一样的开发商使用不一样的编码页,给这带来了混乱。也就是说,同一个日语字符,在一个机器上可能用0x95和0x5c两个字节表示,而在另外的机器的上则多是0xc9和0xbd。这样一事每次交换数据都要进行一次转换(称为码表转换(charmap conversion)或码集转换(codeset conversion))。
什么是Unicode?它是如何解决这个问题的?
每一种语言的不一样的编码页,增长了那些须要支持不一样语言的软件的复杂度。于是人们制定了一个世界标准,叫作unicode(
http://www.unicode.org).Unicode为每一个字符提供了惟一的特定数值,不论在什么平台上、不论在什么软件中,也不论什么语言。也就是说,它世界上使用的全部字符都列出来,并给每个字符一个惟一特定数值。
什么是UTF-8?它与UNICODE是一回事吗?
Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。但这还不够,它不能覆盖所有历史上的文字,也不能解决传输的问题(implantation head-ache's),尤为在那些基于网络的应用中。已有的软件必须作大量的工做来程序16位的数据。
所以,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。在讨论Unicode时,搞清楚哪一种编码方式很是重要。Unicdoe相关的技术介绍参见
http://www.unicode.org/unicode/standard/principles.html. 话说这个VB6,非常无耻,竟然内置了支持Unicode的功能,也就是说,当你读入一个字符串时,它根据本地缺省语言的对应关系将之转换为Unicode,输出时,再从Unicode转换为本地编码。一方面,它固然方便啦,随便出个什么语言的版本都好方便的,并且在Unicode的系统上,如NT,那它可就如鱼得水,Unicode毕竟是软件发展的方向,像如今中文Win9X使用的GBK内码,实际上就是向着Unicode走了一大步。但是在另外一方面,这种支持实际上极大地延缓了字符串的处理时间!想一想看,若是咱们从文件里读一行并显示,原本是很简单的事情,但是在VB6里面,实际上多了一段转换到Unicode的时间,若是咱们用字符串从原文件里读一行,而后分析,再写到目的文件里去,实际上就多了两重的时间(本地到Unicode,unicode到本地)。固然对于这种小事,高手们想必也都有处理的办法(如用byte数组来代替字符串) 说了这么一大堆Unicode的坏话,还没说到正题呢,因为VB6内置对Unicode的支持,而Unicode里面分别和 GBK 以及Big5汉字都有对应关系,因此要实现转换也只是一件小事,下面咱们就有请本次女主角出场。(哗哗哗哗……掌声不绝。) 函数strConv! 这个美眉你们可能在VB5里面也都见过的,她有一些保镖,能够帮她把字符串在Unicode和本地编码之间转换,而在VB6里面呢,strConv又多了一个保镖!你们请仔细看: strConv(string,conversion) `VB5 StrConv(string,conversion,LCID) `VB6 Java内核是unicode的,就连class文件也是,可是不少媒体,包括文件/流的保存方式 是使用字节流的。 所以Java要对这些字节流经行转化。char是unicode的,而byte是字节. Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度, 能够用来告诉你,你用的Convertor。其中两个很经常使用的静态函数是 public static ByteToCharConverter getDefault() ; public static ByteToCharConverter getConverter(String encoding); 若是你不指定converter,则系统会自动使用当前的Encoding,GB平台上用GBK,EN平台上用 8859_1 咱们来就一个简单的例子: "你"的gb码是:0xC4E3 ,unicode是0x4F60 你用: --encoding="gb2312"; --byte b[]={(byte)"u00c4",(byte)"u00E3"}; --convertor=ByteToCharConverter.getConverter(encoding); --char [] c=converter.convertAll(b); --for(int i=0;i0xC4,0x00E3->0xE3,所以0xC4,0xE3被放进了 1.网页传参数不提倡用get方法,并且用户能够调整是否用utf-8发送 /////////// 这一行要注意了 2.建议jsp中最好不要用,实际上加不加这句都有实现中文正常显示的方案,我认为不加方便些,至少不用写这些代码,以下的配置我认为可使中文正常显示: a.全部的javabean用iso8859-1编译 b.jsp文件中不要写以上charset=gb2312的语句(写了反而错) 这段更重要了,作后台sql的都看看吧 咱们的目标是,任一国家的客户端经过Form向Server发送信息,Server把信息存入数据库中,客户端在检索时仍然可以看到本身发送的正确信息。事实上,咱们要保证,最终Server中的SQL语句中保存的时包含客户端发送文字的正确Unicode编码;DBC与数据库通信时采用的编码方式能包含客户端发送的文字信息,事实上,最好让JDBC直接使用UNICODE/UTF8与数据库通信!这样就能够确保不会丢失信息;Server向客户端发送的信息时也要采用不丢失信息的编码方式,也能够是Unicode/Utf8。 若是不指定Form的Enctype属性,Form将把输入的内容依照当前页面的编码字符集urlencode以后再提交,服务器端获得是urlencoding的字符串。编码后获得的urlencoding字符串是与页面的编码相关的,如gb2312编码的页面提交"中文测试",获得的是"%D6%D0%CE%C4%B2%E2%CA%D4",每一个"%"后跟的是16进制的字符串;而在UTF8编码时获得的倒是"%E4%B8%AD%E6%96%87%E6%B5%8B%E8%AF%95",由于GB2312编码中一个汉字是16位的,而UTF8中一个汉字倒是24位的。中日韩三国的ie4以上浏览器均支持UTF8编码,这种方案确定包涵了这三国语言,因此咱们若是让Html页面使用UTF8编码那么将至少能够支持这三国语言。 可是,若是咱们html/Jsp页面使用UTF8编码,由于应用程序服务器可能不知道这种状况,由于若是浏览器发送的信息不包含charset信息,至多Server知道读到Accept-Language请求投标,咱们知道仅靠这个投标是不能获知浏览器所采用编码的,因此应用程序服务器不能正确解析提交的内容,为何?由于Java中的全部字符串都是Unicode16位编码的,HttpServletRequest.request(String)的功能就是把客户端提交的Urlencode编码的信息转为Unicode字符串,有些Server只能认为客户端的编码和Server平台相同,简单地使用URLDecoder.decode(String)方法直接解码,若是客户端编码刚好和Server相同,那么就能够获得正确地字符串,不然,若是提交地字符串中包含了当地字符,那么将会致使垃圾信息。