当前位置:首页 > 全部子站 > IT > 思科认证

Java编程技术中汉字问题的分析及解决

来源:长理培训发布时间:2017-12-21 16:37:01

 百度广告

  在基于 Java 语言的编程中,我们经常碰到汉字的处理及显示的问题。一大堆看不懂的乱码肯定不是我们愿意看到的显示效果,怎样才能够让那些汉字正确显示呢?Java语言默认的编码方式是UNICODE,而我们中国人通常使用的文件和数据库都是基于GB2312或者BIG5等方式编码的,怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢?将从汉字编码的常识入手,结合Java编程实例,分析以上两个问题并提出解决它们的方案。

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

  汉字编码的常识

  我们知道,英文字符一般是以一个字节来表示的,最常用的编码方法是 ASCII 。但一个字节最多只能区分256个字符,而汉字成千上万,所以现在都以双字节来表示汉字,为了能够与英文字符分开,每个字节的最高位一定为1,这样双字节最多可以表示64K格字符。我们经常碰到的编码方式有 GB2312、BIG5、UNICODE 等。关于具体编码方式的详细资料,有兴趣的读者可以查阅相关资料。我肤浅谈一下和我们关系密切的 GB2312 和 UNICODE。GB2312 码,中华人民共和国国家标准汉字信息交换用编码,是一个由中华人民共和国国家标准总局发布的关于简化汉字的编码,通行于中国大陆地区及新加坡,简称国标码。两个字节中,第一个字节(高字节)的值为区号值加32(20H),第二个字节(低字节)的值为位号值加32(20H),用这两个值来表示一个汉字的编码。UNICODE 码是微软提出的解决多国字符问题的多字节等长编码,它对英文字符采取前面加"0"字节的策略实现等长兼容。如 "A" 的 ASCII 码为0x41,UNICODE 就为0x00,0x41。利用特殊的工具各种编码之间可以互相转换。

  Java 中文问题的初步认识

  我们基于 Java 编程语言进行应用开发时,不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE,而我们通常使用的数据库及文件都是基于 GB2312 编码的,我们经常碰到这样的情况:浏览基于 JSP 技术的网站看到的是乱码,文件打开后看到的也是乱码,被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。

 

String sEnglish = "apple";

String sChinese = "苹果";

String s = "苹果 apple ";


Java 字节码-> ;虚拟机->操作系统->显示设备"的过程。在上述过程中的每一步骤,我们都必须正确地处理汉字的编码,才能够使最终的显示结果正确。

  " Java 源代码-> Java 字节码",标准的 Java 编译器 javac 使用的字符集是系统默认的字符集,比如在中文 Windows 操作系统上就是 GBK ,而在 Linux 操作系统上就是ISO-8859-1,所以大家会发现在 Linux 操作系统上编译的类中源文件中的中文字符都出了问题,解决的办法就是在编译的时候添加 encoding 参数,这样才能够与平台无关。用法是

  javac ?Cencoding GBK。

  " Java 字节码->虚拟机->操作系统", Java 运行环境 (JRE) 分英文版和国际版,但只有国际版才支持非英文字符。 Java 开发工具包 (JDK) 肯定支持多国字符,但并非所有的计算机用户都安装了 JDK 。很多操作系统及应用软件为了能够更好的支持 Java ,都内嵌了 JRE 的国际版本,为自己支持多国字符提供了方便。

  "操作系统->显示设备",对于汉字来说,操作系统必须支持并能够显示它。英文操作系统如果不搭配特殊的应用软件的话,是肯定不能够显示中文的。

  还有一个问题,就是在 Java 编程过程中,对中文字符进行正确的编码转换。例如,向网页输出中文字符串的时候,不论你是用

 

out.println(string);

 


 

String s1 = request.getParameter("keyword");

String s2 = new String(s1.getBytes("ISO-8859-1"),"GBK");


  Java 中文问题的表层分析及处理

 

背景
开发环境 JDK1.15 Vcafe2.0 JPadPro
服务器端 NT IIS Sybase System Jconnect(JDBC)
客户端 IE5.0 Pwin98  

  I.用 JDBC 执行 SELECT 语句从服务器端读取数据(中文)后,将数据用 APPEND 方法加到 TextArea(TA) ,不能正确显示。但加到 List 中时,大部分汉字却可正确显示。

  将数据按"ISO-8859-1" 编码方式转化为字节数组,再按系统缺省编码方式 (Default Character Encoding) 转化为 STRING ,即可在 TA 和 List 中正确显示。

  程序段

 

dbstr2 = results.getString(1);
dbbyte1 = dbstr2.getBytes("iso-8859-1");

  II.处理方式与"取中文"相逆,先将 SQL 语句按系统缺省编码方式转化为字节数组,再按"ISO-8859-1"编码方式转化为 STRING ,最后送去执行,则中文信息可正确写入数据库。

  程序段

 

sqlstmt = tf_input.getText();
dbbyte1 = sqlstmt.getBytes();
_stmt = _con.createStatement();
……

  我们的分析:

  1.经过测试,在 A 情况下,程序运行时系统的缺省编码方式为 GBK 或者 GB2312 。在 B 情况下,程序启动时浏览器的 JAVA 控制台中出现如下错误信息:

  Can't find resource for sun.awt.windows.awtLocalization_zh_CN

  然后系统的缺省编码方式为"8859-1"。

UnsupportedEncodingException。

sun.io.CharToByteDoubleByte.class。

  将该文件拷到服务器端和其它的类放在一起,并在程序的开头 IMPORT 它,在 B 情况下程序仍然无法正常运行。

  如果 JDK 的版本为1.2以上的话,在 B 情况下遇到的问题得到了很好的解决,测试的步骤同上,有兴趣的读者可以尝试一下。

  Java 中文问题的根源分析及解决

  在简体中文 MS Windows 98 + JDK 1.3 下,可以用 System.getProperties() 得到 Java 运行环境的一些基本属性,类 PoorChinese 可以帮助我们得到这些属性。

  类 PoorChinese 的源代码:

  public class PoorChinese {}

  执行 java PoorChinese 后,我们会得到:

  系统变量 file.encoding 的值为 GBK ,user.language 的值为 zh , user.region 的值为 CN ,这些系统变量的值决定了系统默认的编码方式是 GBK 。|||

  在上述系统中,下面的代码将 GB2312 文件转换成 Big5 文件,它们能够帮助我们理解 Java 中汉字编码的转化:

 

import java.io.*;
public class gb2big5 
static int iCharNum=0;
System.out.println("Input GB2312 file, output Big5 file.");
{
System.exit(1);
writeOutput(inputString,args[1]);
}
{
{
Writer out = new OutputStreamWriter(fos, "Big5");
out.close();
catch (IOException e) 
e.printStackTrace();
}
static String readInput(String strInFile)
StringBuffer buffer = new StringBuffer();
{
InputStreamReader isr = new InputStreamReader(fis, "GB2312");
int ch;
-1) 
iCharNum += 1;buffer.append((char)ch);
in.close();
}
{
return null;
}

  GB2312------------------>Unicode------------->Big5

  执行 java gb2big5 gb.txt big5.txt ,如果 gb.txt 的内容是"今天星期三",则得到的文件 big5.txt 中的字符能够正确显示;而如果 gb.txt 的内容是"情人节快乐",则得到的文件 big5.txt 中对应于"节"和"乐"的字符都是符号"?"(0x3F),可见 sun.io.ByteToCharGB2312 和 sun.io.CharToByteBig5 这两个基本类并没有编好。

  正如上例一样, Java 的基本类也可能存在问题。由于国际化的工作并不是在国内完成的,所以在这些基本类发布之前,没有经过严格的测试,所以对中文字符的支持并不像 Java Soft 所声称的那样完美。前不久,我的一位技术上的朋友发信给我说,他终于找到了 Java Servlet 中文问题的根源。两周以来,他一直为 Java Servlet 的中文问题所困扰,因为每面对一个含有中文字符的字符串都必须进行强制转换才能够得到正确的结果(这好象是大家公认的唯一的解决办法)。

  后来,他确实不想如此继续安分下去了,因为这样的事情确实不应该是高级程序员所要做的工作,他就找出 Servlet 解码的源代码进行分析,因为他怀疑问题就出在解码这部分。经过四个小时的奋斗,他终于找到了问题的根源所在。原来他的怀疑是正确的, Servlet 的解码部分完全没有考虑双字节,直接把 %XX 当作一个字符。(原来 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=HttpUtils.parsePostData(……)


  关于 Java 中文问题的总结

  Java 编程语言成长于网络世界,这就要求 Java 对多国字符有很好的支持。 Java 编程语言适应了计算的网络化的需求,为它能够在网络世界迅速成长奠定了坚实的基础。 Java 的缔造者 (Java Soft) 已经考虑到 Java 编程语言对多国字符的支持,只是现在的解决方案有很多缺陷在里面,需要我们付诸一些补偿性的措施。而世界标准化组织也在努力把人类所有的文字统一在一种编码之中,其中一种方案是 ISO10646 ,它用四个字节来表示一个字符。当然,在这种方案未被采用之前,还是希望 Java Soft 能够严格地测试它的产品,为用户带来更多的方便。

  附一个用于从数据库和网络中取出 中文乱码的处理函数,入参是有问题的字符串,出参是问题已经解决了的字符串。

责编:罗莉

发表评论(共0条评论)
请自觉遵守互联网相关政策法规,评论内容只代表网友观点,发表审核后显示!

国家电网校园招聘考试直播课程通关班

  • 讲师:刘萍萍 / 谢楠
  • 课时:160h
  • 价格 4580

特色双名师解密新课程高频考点,送国家电网教材讲义,助力一次通关

配套通关班送国网在线题库一套

课程专业名称
讲师
课时
查看课程

国家电网招聘考试录播视频课程

  • 讲师:崔莹莹 / 刘萍萍
  • 课时:180h
  • 价格 3580

特色解密新课程高频考点,免费学习,助力一次通关

配套全套国网视频课程免费学习

课程专业名称
讲师
课时
查看课程
在线题库
面授课程更多>>
图书商城更多>>
在线报名
  • 报考专业:
    *(必填)
  • 姓名:
    *(必填)
  • 手机号码:
    *(必填)
返回顶部