Java编程技术中汉字问题的分析及解决_第1页
Java编程技术中汉字问题的分析及解决_第2页
Java编程技术中汉字问题的分析及解决_第3页
Java编程技术中汉字问题的分析及解决_第4页
Java编程技术中汉字问题的分析及解决_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 HYPERLINK /kt400_hhx/article/details/1641590 o 字体编码学习-Java 编程技术中汉字问题的分析及解决 JAVA汉字显示问题的解决方案 字体编码学习-Java 编程技术中汉字问题的分析及解决 JAVA汉字显示问题的解决方案分类: HYPERLINK /kt400_hhx/article/category/307815 java相关2007-06-07 02:311593人阅读 HYPERLINK /kt400_hhx/article/details/1641590 l comments 评论(0) HYPERLINK javascript:voi

2、d(0); o 收藏 收藏 HYPERLINK /kt400_hhx/article/details/1641590 l report o 举报 举报字体编码学习-关键字:USC,Unicode,utf-8,gb2312,字库什么是编码为了交流信息,所以对字符进行了统一的编码。UCS和ISO10646 ISO10646定义了通用字符集(Universal Character Set,UCS).UCS是国际标准编码,包含了全球所有字符。UCS使用31bit进行编码。现在只分配了前65534个码位,这个16位的子集称为基本多语言面(BMP)。什么Unicode Unicode编码是UCS级别的实现

3、。Unicode编码全码为4个字节,所有字符都使用等的编码方式,现在只使用两个字节编码。兼容UCS定义的BMPGB2313与Unicode GB2312是中国定制的国际准标编码,由两个字节组成,最高位为1表示汉字,最高为0表示是英文。 GB2312与区位码存在数值关系,区位码+20HGB2312 GB2312与Unicode的转换不成数学关系,只能通过映射表来实现。 GB2312为年定义的基本编码扩展编码有 GBK GB18030 GB13000与GBK不兼容,只是使用了相同的词汇. 最新为GB16500-95与unicode3.0兼容Unicode与UTF-8 Utf-8是为了兼容软件处理的

4、编码,是unicode的另一种表示方式。使用变化的方式编码,第一字节表示字符的长度,后面的字符以10开头表示编码。0开头表示ascii编码。 例如:Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为 11000010 10101001 = 0 xC2 0 xA9字库与编码关系 字库是编码表字符显示的描述文件。字符编码是在字库中查询需要显示的字符的索引值。 不同的编码就应该有不同的字库,比如unicode编码就有unicode的字库。Gb2312编码就有gb2312的字库。字库格式 字库的格式主要有TrueType(ttf),PostScript

5、(rip),OpenType等 TrueType是微软定义的字库格式,主要用于软件显示这种要求精度不高的环境, PostScript是Adobe定义的字库格式,主要用于排版印刷等大字打印精度要求很高的环境。 OpenType是TrueType与PostScript的综合格式,并且是使用了unicode的编码。字体引擎 字体引擎用于读取字库,显示文字,文字转换等操作。现在免费的字体引擎有FreeType.参考文献 UTF-8 and Unicode FAQ by Markus Kuhn HYPERLINK /linux/TrueType-HOWTO.html /linux/TrueType-HO

6、WTO.html HYPERLINK /Info/55/Info16006/ /Info/55/Info16006/ HYPERLINK /fonts/TTRefMan/index.html /fonts/TTRefMan/index.html/以前一直对utf、unicode、ascII还有GBK编码方式不太了解,只知道如果有中文的话一般用utf-8或GBK存储,今天正好又接触到了这个问题就google了下。ASCII是用来表示英文的一种编码规范,表示的最大字符数为256个,每个字符占1个字节。如果只用来表示英文应该是绰绰有余了,可是还要表示中文、阿拉伯文所以就有很大的不足了,于是就产生了G

7、B2312。很多人应该对这个比较了解,很多国内网页指定的编码都是GB2312的,它其实是对ASCII的一种扩展,是每个国家自己制定的编码规范,比如一个中文字符是由两个扩展ASCII字符表示。但因为GB2312是国家标准所以会有一些问题,记得我们小时候玩一些繁体游戏时需要借助一些南极星之类的软件转换编码吗?因为台湾很多用的都是big5编码,他和GB2312的编码格式还是类似的,会显示出一些奇怪的文字或是偶尔也会有个别汉字。后来因为GB2312所包含的汉字太少了,所以又扩展出来GBK编码。GBK包括了大部分的汉字,并且还加入了big5中几乎所有的繁体字体(但big5和GBK中的繁体字体并不兼容)。

8、之后还有GB18030编码,其实主要还是字符集的变化。ASCIIGB2312GBKGB18030他们都是向下兼容的,区分英文编码和中文编码的方法是高字节的最高位不为0,其实GB中文编码都是双字节字符集。因为GB编码都是国家标准,所以如果要解决中文问题不能从扩展ASCII角度入手了,于是出现了unicode和utf。unicode分为UCS-2、UCS-4,目前常用的是UCS-2是用2个字节为字符编码,可以表示的数为216=65535,基本可以表示欧美和大部分亚洲汉字,并且因为UCS-2是双字节的所以每个汉字或英文都是由1个unicode构成,那拆字和统计字数比ASCII方便了很多。似乎unic

9、ode是比较完美了,可是它却有一个很致命的缺点,就是并不能和ASCII兼容。ASCII字符是单个字节的,比如A的ASCII是65。而Unicode是双字节的,比如A的Unicode是0065,这就造成了一个非常大的问题:以前处理ASCII的那套机制不能被用来处理Unicode了 。另一个更加严重的问题是,C语言使用/0作为字符串结尾,而Unicode里恰恰有很多字符都有一个字节为0,这样一来,C语言的字符串函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉 。于是出现了utf,它是将Unicode编码规则和计算机的实际编码对应起来的一个规则。现在流行的U

10、TF有2种:UTF-8和UTF-16。UTF-8是以8位为单元对UCS进行编码,它定义了一种区间规则,这种规则可以和ASCII编码保持最大程度的兼容 。具体的编码方式大家可以搜索一下,俺也只是一些浅显的了解,如果有不对的地方请大家指出来/Unicode:制定的编码机制, 要将全世界常用文字都函括进去.在1.0中是16位编码, 由U+0000到U+FFFF. 每个2byte码对应一个字符; 在2.0开始抛弃了16位限制, 原来的16位作为基本位平面, 另外增加了16个位平面, 相当于20位编码, 编码范围0到0 x10FFFF.UCS:ISO制定的ISO10646标准所定义的 Universal

11、 Character Set, 采用4byte编码.Unicode与UCS的关系:ISO与是两个不同的组织, 因此最初制定了不同的标准; 但自从unicode2.0开始, unicode采用了与ISO 10646-1相同的字库和字码, ISO也承诺ISO10646将不会给超出0 x10FFFF的UCS-4编码赋值,使得两者保持一致.UCS的编码方式:UCS-2, 与unicode的2byte编码基本一样.UCS-4, 4byte编码, 目前是在UCS-2前加上2个全零的byte.UTF: Unicode/UCS Transformation FormatUTF-8, 8bit编码, ASCII

12、不作变换, 其他字符做变长编码, 每个字符1-3 byte. 通常作为外码. 有以下优点:* 与CPU字节顺序无关, 可以在不同平台之间交流* 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码)UTF-16, 16bit编码, 是变长码, 大致相当于20位编码, 值在0到0 x10FFFF之间, 基本上就是unicode编码的实现. 它是变长码, 与CPU字序有关, 但因为最省空间, 常作为网络传输的外码.UTF-16是unicode的preferred encoding.UTF-32, 仅使用了unicode范围(0到0 x10

13、FFFF)的32位编码, 相当于UCS-4的子集.UTF与unicode的关系:Unicode是一个字符集, 可以看作为内码.而UTF是一种编码方式, 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接就是unicode编码, 没有变换, 但它包含了0 x00在编码内, 头256字节码的第一个byte都是0 x00, 在操作系统(C语言)中有特殊意义, 会引起问题. 采用UTF-8编码对unicode的直接编码作些变换可以避免这问题,并带来一些优点.中国国标编码:GB 13000: 完全等同于ISO 10646-1/Unicode 2.1, 今后也将随ISO 106

14、46/Unicode的标准更改而同步更改.GBK: 对GB2312的扩充, 以容纳GB2312字符集范围以外的Unicode 2.1的统一汉字部分, 并且增加了部分unicode中没有的字符.GB 18030-2000: 基于GB 13000, 作为Unicode 3.0的GBK扩展版本, 覆盖了所有unicode编码, 地位等同于UTF-8, UTF-16, 是一种unicode编码形式. 变长编码, 用单字节/双字节/4字节对字符编码. GB18030向下兼容GB2312/GBK.GB 18030是中国所有非手持/嵌入式计算机系统的强制实施标准./彻底解决程序乱码问题 由于程序编程过程中存

15、在众多的编码集,而这些编码集又各自有自己的方法来表示一个中文字符。由此,造成我们的程序显示中文的时候乱码。最多的是本来是中文,但结果显示为问号? 这篇文章从我碰到过的问题来从根本上解决乱码的问题,反正我用这个方法是百战百胜_嘎嘎 我们知道,在我们的中文系统中使用的是“GBK”编码集。 也就是说,比如我们从本地系统中读入一个包含中文内容的.txt文件,那么我们从这个磁盘空间所获得是流文件是个经过“GBK”的。 但是,假如我们的JVM默认的编码集是“ISO-8859-1”,那么这个流文件经过我们的JVM编码就变成一个Unicode的字符或者字符串。 是不是说的很抽象。 下面我具体解释一下。 什么是

16、编码?编码说白了就是从字节到字符(Unicode)的过程,因为我们的字符或字符串在JVM中是用Unicode表示的,也就是说编码实质上是获取一个Unicode码的过程。 我再来解释一下解码?解码就是把JVM里的Unicode码转换成我们本地字符集所表示的字节流。 如果在编程过程中,JVM默认的字符集和我们的中文系统,或者数据库文件等采用的字符集不一样。 这样的情况下,如果我们仅仅是编码,而不去解码。也就说把本来用“GBK”的字节流采用“ISO-8859-1”转换成字符或字符串,这个时候就产生了乱码。 当然,现在JVM和中文系统默认的编码集已经一样了,所以产生这种情况的很少。但是在读取数据库文件

17、的时候依然会经常碰到这种情况。所以,我一贯主张从本质上来了解一个知识,然后才能融会贯通,应用自如,这是高手的境界,当然,我不能算高手_哈哈 好了,如果你现在还不明白编码解码怎么回事?以及乱码产生的原因。我想你可以去撞墙了。 那么,编码的时候两个系统的字符集不一致,该怎么办呢?怎么样把他们变成一致? 如果有可以直接改变系统字符集的方法,那当然是最好的了。比如在JVM里 Properties pps = System.getProperties(); pps.put(file.encoding,GBK); 这样,就把JVM的默认字符集改变成“GBK”了。 那么,如果没有改怎么办? 什么?没办法?那

18、是不可能滴,没有程序解决不了的问题,这也是偶滴名言,嘎嘎!当然要再次编码了,或者说重新编码! 还记得不?刚才我们解码的时候得到一个利用JVM解码的字符或字符串(也可以说Unicode)好,如果不记得,麻烦你再看看上面写的,记性太差了! 我们利用这个字符或字符串再重新编码。我们把这个字符或字符串再次现出原形,也就是字节数组。 byte data = str.getBytes(ISO-8859-1);好,现在又获得了“ISO-8859-1”字符集下的字节数组。这个里面就完整的存放着我们想要的汉字,哈哈。得到了字节数组,不就好办了吗?还不会?没关系,我教你!String newstr = new S

19、tring(data,“GBK”);好了,得到了我们完整的字符串了!编码变成!这个字符串就是我们要的中文系统下的字符串,它又经过我们“GBK”编码过了!可以放心的输出到中文系统下了。其实说白了,编码解码就是把我们从系统得到的字符转换成字节数组,然后对它用系统字符集加工,加工完后再重新包装,再把它输出。/Java 编程技术中汉字问题的分析及解决在基于 Java 语言的编程中,我们经常碰到汉字的处理及显示的问题。一大堆看不懂的乱码肯定不是我们愿意看到的显示效果,怎样才能够让那些汉字正确显示呢?Java 语言默认的编码方式是UNICODE ,而我们中国人通常使用的文件和数据库都是基于 GB2312或

20、者 BIG5 等方式编码的,怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢?本文将从汉字编码的常识入手,结合 Java 编程实例,分析以上两个问题并提出解决它们的方案。现在 Java 编程语言已经广泛应用于互联网世界,早在 Sun 公司开发 Java 语言的时候,就已经考虑到对非英文字符的支持了。Sun 公司公布的 Java 运行环境(JRE)本身就分英文版和国际版,但只有国际版才支持非英文字符。不过在 Java 编程语言的应用中,对中文字符的支持并非如同 Java Soft 的标准规范中所宣称的那样完美,因为中文字符集不只一个,而且不同的操作系统对中文字符的支持也不尽相同,所以会有

21、许多和汉字编码处理有关的问题在我们进行应用开发中困扰着我们。有很多关于这些问题的解答,但都比较琐碎,并不能够满足大家迫切解决问题的愿望,关于 Java 中文问题的系统研究并不多,本文从汉字编码常识出发,分析 Java 中文问题,希望对大家解决这个问题有所帮助。汉字编码的常识我们知道,英文字符一般是以一个字节来表示的,最常用的编码方法是 ASCII 。但一个字节最多只能区分256个字符,而汉字成千上万,所以现在都以双字节来表示汉字,为了能够与英文字符分开,每个字节的最高位一定为1,这样双字节最多可以表示64K格字符。我们经常碰到的编码方式有 GB2312、BIG5、UNICODE 等。关于具体编

22、码方式的详细资料,有兴趣的读者可以查阅相关资料。我肤浅谈一下和我们关系密切的 GB2312 和 UNICODE。GB2312 码,中华人民共和国国家标准汉字信息交换用编码,是一个由中华人民共和国国家标准总局发布的关于简化汉字的编码,通行于中国大陆地区及新加坡,简称国标码。两个字节中,第一个字节(高字节)的值为区号值加32(20H),第二个字节(低字节)的值为位号值加32(20H),用这两个值来表示一个汉字的编码。UNICODE 码是微软提出的解决多国字符问题的多字节等长编码,它对英文字符采取前面加“0”字节的策略实现等长兼容。如 “A” 的 ASCII 码为0 x41,UNICODE 就为0

23、x00,0 x41。利用特殊的工具各种编码之间可以互相转换。Java 中文问题的初步认识我们基于 Java 编程语言进行应用开发时,不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE,而我们通常使用的数据库及文件都是基于 GB2312 编码的,我们经常碰到这样的情况:浏览基于 JSP 技术的网站看到的是乱码,文件打开后看到的也是乱码,被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。String sEnglish = “apple”;String sChinese = “苹果”;String s = “苹果 apple ”;sEnglish 的长度

24、是5,sChinese的长度是4,而 s 默认的长度是14。对于 sEnglish来说, Java 中的各个类都支持得非常好,肯定能够正确显示。但对于 sChinese 和 s 来说,虽然 Java Soft 声明 Java 的基本类已经考虑到对多国字符的支持(默认 UNICODE编码),但是如果操作系统的默认编码不是 UNICODE ,而是国标码等。从 Java 源代码到得到正确的结果,要经过 “Java 源代码- Java 字节码- ;虚拟机-操作系统-显示设备”的过程。在上述过程中的每一步骤,我们都必须正确地处理汉字的编码,才能够使最终的显示结果正确。“ Java 源代码- Java 字

25、节码”,标准的 Java 编译器 javac 使用的字符集是系统默认的字符集,比如在中文 Windows 操作系统上就是 GBK ,而在 Linux 操作系统上就是ISO-8859-1,所以大家会发现在 Linux 操作系统上编译的类中源文件中的中文字符都出了问题,解决的办法就是在编译的时候添加 encoding 参数,这样才能够与平台无关。用法是javac encoding GBK。“ Java 字节码-虚拟机-操作系统”, Java 运行环境 (JRE) 分英文版和国际版,但只有国际版才支持非英文字符。 Java 开发工具包 (JDK) 肯定支持多国字符,但并非所有的计算机用户都安装了 J

26、DK 。很多操作系统及应用软件为了能够更好的支持 Java ,都内嵌了 JRE 的国际版本,为自己支持多国字符提供了方便。“操作系统-显示设备”,对于汉字来说,操作系统必须支持并能够显示它。英文操作系统如果不搭配特殊的应用软件的话,是肯定不能够显示中文的。还有一个问题,就是在 Java 编程过程中,对中文字符进行正确的编码转换。例如,向网页输出中文字符串的时候,不论你是用out.println(string); / string 是含中文的字符串还是用,都必须作 UNICODE 到 GBK 的转换,或者手动,或者自动。在 JSP 1.0中,可以定义输出字符集,从而实现内码的自动转换。用法是但是

27、在一些 JSP 版本中并没有提供对输出字符集的支持,(例如 JSP 0.92),这就需要手动编码输出了,方法非常多。最常用的方法是String s1 = request.getParameter(“keyword”);String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);getBytes 方法用于将中文字符以“ISO-8859-1”编码方式转化成字节数组,而“GBK”是目标编码方式。我们从以ISO-8859-1方式编码的数据库中读出中文字符串 s1 ,经过上述转换过程,在支持 GBK 字符集的操作系统和应用软件中就能够正确显示中文字符串

28、s2 。Java 中文问题的表层分析及处理背景开发环境JDK1.15Vcafe2.0JPadPro服务器端NT IISSybase SystemJconnect(JDBC)客户端IE5.0Pwin98.CLASS 文件存放在服务器端,由客户端的浏览器运行 APPLET , APPLET 只起调入 FRAME 类等主程序的作用。界面包括 Textfield ,TextArea,List,Choice 等。I. 取中文用 JDBC 执行 SELECT 语句从服务器端读取数据(中文)后,将数据用 APPEND 方法加到 TextArea(TA) ,不能正确显示。但加到 List 中时,大部分汉字却可

29、正确显示。将数据按“ISO-8859-1” 编码方式转化为字节数组,再按系统缺省编码方式 (Default Character Encoding) 转化为 STRING ,即可在 TA 和 List 中正确显示。程序段如下:dbstr2 = results.getString(1);/After reading the result from DB server,converting it to string.dbbyte1 = dbstr2.getBytes(“iso-8859-1”);dbstr1 = new String(dbbyte1);在转换字符串时不采用系统默认编码方式,而直接采用

30、“ GBK” 或者 “GB2312” ,在A 和 B 两种情况下,从数据库取数据都没有问题。II. 写中文到数据库处理方式与“取中文”相逆,先将 SQL 语句按系统缺省编码方式转化为字节数组,再按“ISO-8859-1”编码方式转化为 STRING ,最后送去执行,则中文信息可正确写入数据库。程序段如下:sqlstmt = tf_input.getText();/Before sending statement to DB server,converting it to sql statement.dbbyte1 = sqlstmt.getBytes();sqlstmt = newString

31、(dbbyte1,”iso-8859-1”);_stmt = _con.createStatement();_stmt.executeUpdate(sqlstmt);问题:如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时(称为 A 情况),上述程序代码可正确执行。但是如果客户机只有浏览器,而没有 JDK 和 CLASSPATH 时(称为 B 情况),则汉字无法正确转换。我们的分析:1.经过测试,在 A 情况下,程序运行时系统的缺省编码方式为 GBK 或者 GB2312 。在B 情况下,程序启动时浏览器的 JAVA 控制台中出现如下错误信息:Cant find

32、resource for sun.awt.windows.awtLocalization_zh_CN然后系统的缺省编码方式为“8859-1”。2.如果在转换字符串时不采用系统缺省编码方式,而是直接采用 “GBK” 或“GB2312”,则在 A 情况下程序仍然可正常运行,在 B 情况下,系统出现错误:UnsupportedEncodingException。3.在客户机上,把 JDK 的 CLASSES.ZIP 解压后,放在另一个目录中, CLASSPATH 只包含该目录。然后一边逐步删除该目录中的 .CLASS 文件,另一边运行测试程序,最后发现在一千多个 CLASS 文件中,只有一个是必不可

33、少的,该文件是:sun.io.CharToByteDoubleByte.class。将该文件拷到服务器端和其它的类放在一起,并在程序的开头 IMPORT 它,在 B 情况下程序仍然无法正常运行。4.在 A 情况下,如果在 CLASSPTH 中去掉 sun.io.CharToByteDoubleByte.class ,则程序运行时测得默认编码方式为“8859-1”,否则为 “GBK” 或 “GB2312” 。如果 JDK 的版本为1.2以上的话,在 B 情况下遇到的问题得到了很好的解决,测试的步骤同上,有兴趣的读者可以尝试一下。/bJava 中文问题的根源分析及解决/b在简体中文 MS Wind

34、ows 98 + JDK 1.3 下,可以用 System.getProperties() 得到 Java 运行环境的一些基本属性,类 PoorChinese 可以帮助我们得到这些属性。类 PoorChinese 的源代码:public class PoorChinese public static void main(String args) System.getProperties().list(System.out); 执行 java PoorChinese 后,我们会得到:系统变量 file.encoding 的值为 GBK ,user.language 的值为 zh , user.r

35、egion 的值为 CN ,这些系统变量的值决定了系统默认的编码方式是 GBK 。在上述系统中,下面的代码将 GB2312 文件转换成 Big5 文件,它们能够帮助我们理解Java 中汉字编码的转化:import java.io.*;import java.util.*;public class gb2big5 static int iCharNum=0;public static void main(String args) System.out.println(Input GB2312 file, output Big5 file.);if (args.length!=2) System.

36、err.println(Usage: jview gb2big5 gbfile big5file);System.exit(1); String inputString = readInput(args0);writeOutput(inputString,args1);System.out.println(Number of Characters in file: +iCharNum+.);static void writeOutput(String str, String strOutFile) try FileOutputStream fos = new FileOutputStream(

37、strOutFile);Writer out = new OutputStreamWriter(fos, Big5);out.write(str);out.close();catch (IOException e) e.printStackTrace();e.printStackTrace();static String readInput(String strInFile) StringBuffer buffer = new StringBuffer();try FileInputStream fis = new FileInputStream(strInFile);InputStreamR

38、eader isr = new InputStreamReader(fis, GB2312);Reader in = new BufferedReader(isr);int ch;while (ch = in.read() -1) iCharNum += 1;buffer.append(char)ch);in.close();return buffer.toString();catch (IOException e) e.printStackTrace();return null;编码转化的过程如下: ByteToCharGB2312 CharToByteBig5GB2312UnicodeBi

39、g5执行 java gb2big5 gb.txt big5.txt ,如果 gb.txt 的内容是“今天星期三”,则得到的文件 big5.txt 中的字符能够正确显示;而如果 gb.txt 的内容是“情人节快乐”,则得到的文件 big5.txt 中对应于“节”和“乐”的字符都是符号“?”(0 x3F),可见 sun.io.ByteToCharGB2312 和 sun.io.CharToByteBig5 这两个基本类并没有编好。正如上例一样, Java 的基本类也可能存在问题。由于国际化的工作并不是在国内完成的,所以在这些基本类发布之前,没有经过严格的测试,所以对中文字符的支持并不像Java S

40、oft 所声称的那样完美。前不久,我的一位技术上的朋友发信给我说,他终于找到了 Java Servlet 中文问题的根源。两周以来,他一直为 Java Servlet 的中文问题所困扰,因为每面对一个含有中文字符的字符串都必须进行强制转换才能够得到正确的结果(这好象是大家公认的唯一的解决办法)。后来,他确实不想如此继续安分下去了,因为这样的事情确实不应该是高级程序员所要做的工作,他就找出 Servlet 解码的源代码进行分析,因为他怀疑问题就出在解码这部分。经过四个小时的奋斗,他终于找到了问题的根源所在。原来他的怀疑是正确的, Servlet 的解码部分完全没有考虑双字节,直接把 %XX 当作

41、一个字符。(原来 Java Soft 也会犯这幺低级的错误!)如果你对这个问题有兴趣或者遇到了同样的烦恼的话,你可以按照他的步骤对 Servlet.jar 进行修改:找到源代码 HttpUtils 中的 static private String parseName ,在返回前将 sb(StringBuffer) 复制成 byte bs ,然后 return new String(bs,”GB2312”)。作上述修改后就需要自己解码了:HashTable form=HttpUtils .parseQueryString(request.getQueryString()或者form=HttpUt

42、ils.parsePostData()千万别忘了编译后放到 Servlet.jar 里面。五、 关于 Java 中文问题的总结Java 编程语言成长于网络世界,这就要求 Java 对多国字符有很好的支持。 Java 编程语言适应了计算的网络化的需求,为它能够在网络世界迅速成长奠定了坚实的基础。 Java 的缔造者 (Java Soft) 已经考虑到 Java 编程语言对多国字符的支持,只是现在的解决方案有很多缺陷在里面,需要我们付诸一些补偿性的措施。而世界标准化组织也在努力把人类所有的文字统一在一种编码之中,其中一种方案是 ISO10646 ,它用四个字节来表示一个字符。当然,在这种方案未被采

43、用之前,还是希望 Java Soft 能够严格地测试它的产品,为用户带来更多的方便。附一个用于从数据库和网络中取出中文乱码的处理函数,入参是有问题的字符串,出参是问题已经解决了的字符串。 String parseChinese(String in) String s = null; byte temp ; if (in = null) System.out.println(Warn:Chinese null founded!); return new String(); try temp=in.getBytes(iso-8859-1); temp=in.getBytes(iso-8859-1)

44、; s = new String(temp); System.out.println(Warn:Chinese null founded!); return new String(); try temp=in.getBytes(iso-8859-1); s = new String(temp); catch(UnsupportedEncodingException e) System.out.println (e.toString(); return s; 作者简介段明辉,清华大学电子工程系学生现在正在清华大学微电子学研究所从事 Java 智能卡微处理器的研究和开发yaya_316 www68

45、207295领导BBS 水木清华站的 Java 讨论组,为众多 Java 技术应用者提供解决方案/JAVA汉字显示问题的解决方案 在基于 Java 语言的编程中,我们经常碰到汉字的处理及显示的问题。一大堆看不懂的乱码肯定不是我们愿意看到的显示效果,怎样才能够让那些汉字正确显示呢?Java 语言默认的编码方式是UNICODE ,而我们中国人通常使用的文件和数据库都是基于 GB2312 或者 BIG5 等方式编码的,怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢?本文将从汉字编码的常识入手,结合 Java编程实例,分析以上两个问题并提出解决它们的方案。现在 Java 编程语言已经广泛应用

46、于互联网世界,早在 Sun 公司开发 Java 语言的时候,就已经考虑到对非英文字符的支持了。Sun 公司公布的 Java 运行环境(JRE)本身就分英文版和国际版,但只有国际版才支持非英文字符。不过在 Java 编程语言的应用中,对中文字符的支持并非如同 JavaSoft 的标准规范中所宣称的那样完美,因为中文字符集不只一个,而且不同的操作系统对中文字符的支持也不尽相同,所以会有许多和汉字编码处理有关的问题在我们进行应用开发中困扰着我们。有很多关于这些问题的解答,但都比较琐碎,并不能够满足大家迫切解决问题的愿望,关于 Java 中文问题的系统研究并不多,本文从汉字编码常识出发,分析 Java

47、 中文问题,希望对大家解决这个问题有所帮助。一、汉字编码的常识我们知道,英文字符一般是以一个字节来表示的,最常用的编码方法是 ASCII 。但一个字节最多只能区分256个字符,而汉字成千上万,所以现在都以双字节来表示汉字,为了能够与英文字符分开,每个字节的最高位一定为1,这样双字节最多可以表示64K格字符。我们经常碰到的编码方式有 GB2312、BIG5、UNICODE 等。关于具体编码方式的详细资料,有兴趣的读者可以查阅相关资料。我肤浅谈一下和我们关系密切的 GB2312 和 UNICODE。GB2312 码,中华人民共和国国家标准汉字信息交换用编码,是一个由中华人民共和国国家标准总局发布的

48、关于简化汉字的编码,通行于中国大陆地区及新加坡,简称国标码。两个字节中,第一个字节(高字节)的值为区号值加32(20H),第二个字节(低字节)的值为位号值加32(20H),用这两个值来表示一个汉字的编码。UNICODE 码是微软提出的解决多国字符问题的多字节等长编码,它对英文字符采取前面加“0”字节的策略实现等长兼容。如 “A” 的 ASCII码为0 x41,UNICODE 就为0 x00,0 x41。利用特殊的工具各种编码之间可以互相转换。二、Java 中文问题的初步认识我们基于 Java 编程语言进行应用开发时,不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE,而我

49、们通常使用的数据库及文件都是基于 GB2312 编码的,我们经常碰到这样的情况:浏览基于 JSP 技术的网站看到的是乱码,文件打开后看到的也是乱码,被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。String sEnglish = “apple”;String sChinese = “苹果”;String s = “苹果 apple ”;sEnglish 的长度是5,sChinese的长度是4,而 s 默认的长度是14。对于 sEnglish来说, Java中的各个类都支持得非常好,肯定能够正确显示。但对于 sChinese 和 s 来说,虽然 Java Soft 声

50、明Java 的基本类已经考虑到对多国字符的支持(默认 UNICODE 编码),但是如果操作系统的默认编码不是 UNICODE ,而是国标码等。从 Java 源代码到得到正确的结果,要经过 “Java 源代码- Java 字节码- ;虚拟机-操作系统-显示设备”的过程。在上述过程中的每一步骤,我们都必须正确地处理汉字的编码,才能够使最终的显示结果正确。“ Java 源代码- Java 字节码”,标准的 Java 编译器 javac 使用的字符集是系统默认的字符集,比如在中文 Windows 操作系统上就是 GBK ,而在 Linux 操作系统上就是ISO-8859-1,所以大家会发现在 Linu

51、x 操作系统上编译的类中源文件中的中文字符都出了问题,解决的办法就是在编译的时候添加 encoding 参数,这样才能够与平台无关。用法是javac encoding GBK。“ Java 字节码-虚拟机-操作系统”, Java 运行环境 (JRE) 分英文版和国际版,但只有国际版才支持非英文字符。 Java 开发工具包 (JDK) 肯定支持多国字符,但并非所有的计算机用户都安装了 JDK 。很多操作系统及应用软件为了能够更好的支持 Java ,都内嵌了 JRE 的国际版本,为自己支持多国字符提供了方便。“操作系统-显示设备”,对于汉字来说,操作系统必须支持并能够显示它。英文操作系统如果不搭配

52、特殊的应用软件的话,是肯定不能够显示中文的。还有一个问题,就是在 Java 编程过程中,对中文字符进行正确的编码转换。例如,向网页输出中文字符串的时候,不论你是用 out.println(string); / string 是含中文的字符串 还是用 ,都必须作 UNICODE 到 GBK 的转换,或者手动,或者自动。在 JSP 1.0中,可以定义输出字符集,从而实现内码的自动转换。用法是但是在一些 JSP 版本中并没有提供对输出字符集的支持,(例如 JSP 0.92),这就需要手动编码输出了,方法非常多。最常用的方法是String s1 = request.getParameter(“keyw

53、ord”);String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);getBytes 方法用于将中文字符以“ISO-8859-1”编码方式转化成字节数组,而“GBK” 是目标编码方式。我们从以ISO-8859-1方式编码的数据库中读出中文字符串 s1 ,经过上述转换过程,在支持GBK 字符集的操作系统和应用软件中就能够正确显示中文字符串 s2 。三、Java 中文问题的表层分析及处理背景开发环境JDK1.15Vcafe2.0JPadPro服务器端NT IISSybase SystemJconnect(JDBC)客户端IE5.0Pwin98

54、.CLASS 文件存放在服务器端,由客户端的浏览器运行 APPLET , APPLET 只起调入 FRAME 类等主程序的作用。界面包括 Textfield ,TextArea,List,Choice 等。I. 取中文用 JDBC 执行 SELECT 语句从服务器端读取数据(中文)后,将数据用 APPEND 方法加到TextArea(TA) ,不能正确显示。但加到 List 中时,大部分汉字却可正确显示。将数据按“ISO-8859-1” 编码方式转化为字节数组,再按系统缺省编码方式 (DefaultCharacter Encoding) 转化为 STRING ,即可在 TA 和 List 中正

55、确显示。程序段如下:dbstr2 = results.getString(1);/After reading the result from DB server,converting it to string.dbbyte1 = dbstr2.getBytes(“iso-8859-1”);dbstr1 = new String(dbbyte1);在转换字符串时不采用系统默认编码方式,而直接采用“ GBK” 或者 “GB2312” ,在 A 和 B 两种情况下,从数据库取数据都没有问题。II. 写中文到数据库处理方式与“取中文”相逆,先将 SQL 语句按系统缺省编码方式转化为字节数组,再按“IS

56、O-8859-1”编码方式转化为 STRING ,最后送去执行,则中文信息可正确写入数据库。程序段如下:sqlstmt = tf_input.getText();/Before sending statement to DB server,converting it to sql statement.dbbyte1 = sqlstmt.getBytes();sqlstmt = newString(dbbyte1,”iso-8859-1”);_stmt = _con.createStatement();_stmt.executeUpdate(sqlstmt);问题:如果客户机上存在 CLASSP

57、ATH 指向 JDK 的 CLASSES.ZIP 时(称为 A 情况),上述程序代码可正确执行。但是如果客户机只有浏览器,而没有 JDK 和 CLASSPATH 时(称为 B 情况),则汉字无法正确转换。我们的分析:1.经过测试,在 A 情况下,程序运行时系统的缺省编码方式为 GBK 或者 GB2312 。在 B 情况下,程序启动时浏览器的 JAVA 控制台中出现如下错误信息:Cant find resource for sun.awt.windows.awtLocalization_zh_CN然后系统的缺省编码方式为“8859-1”。2.如果在转换字符串时不采用系统缺省编码方式,而是直接采用

58、 “GBK” 或“GB2312”,则在 A情况下程序仍然可正常运行,在 B 情况下,系统出现错误:UnsupportedEncodingException。3.在客户机上,把 JDK 的 CLASSES.ZIP 解压后,放在另一个目录中, CLASSPATH 只包含该目录。然后一边逐步删除该目录中的 .CLASS 文件,另一边运行测试程序,最后发现在一千多个 CLASS 文件中,只有一个是必不可少的,该文件是: sun.io.CharToByteDoubleByte.class。将该文件拷到服务器端和其它的类放在一起,并在程序的开头 IMPORT 它,在 B 情况下程序仍然无法正常运行。4.在

59、 A 情况下,如果在 CLASSPTH 中去掉 sun.io.CharToByteDoubleByte.class ,则程序运行时测得默认编码方式为“8859-1”,否则为 “GBK” 或 “GB2312” 。如果 JDK 的版本为1.2以上的话,在 B 情况下遇到的问题得到了很好的解决,测试的步骤同上,有兴趣的读者可以尝试一下。四、Java 中文问题的根源分析及解决在简体中文 MS Windows 98 + JDK 1.3 下,可以用 System.getProperties() 得到 Java 运行环境的一些基本属性,类 PoorChinese 可以帮助我们得到这些属性。类 PoorChi

60、nese 的源代码:public class PoorChinese public static void main(String args) System.getProperties().list(System.out);执行 java PoorChinese 后,我们会得到:系统变量 file.encoding 的值为 GBK ,user.language 的值为 zh , user.region 的值为 CN,这些系统变量的值决定了系统默认的编码方式是 GBK 。在上述系统中,下面的代码将 GB2312 文件转换成 Big5 文件,它们能够帮助我们理解 Java 中汉字编码的转化:imp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论