当前位置:  技术问答>java相关

为什么编以后的java类,不能显示中文,显示的全是乱码?我用的是j2sdk,系统是win2K

    来源: 互联网  发布时间:2015-03-24

    本文导语:  | java处理中文是有问题;可以用下面的函数解决: public String getStr(String str) {  try { String temp_p=str; byte[] temp_t=temp_p.getBytes("ISO8859-1"); String temp=new String(temp_t); return temp; } catch(Exception e) { } return "null"; } | ...


|
java处理中文是有问题;可以用下面的函数解决:

public String getStr(String str)

try
{
String temp_p=str;
byte[] temp_t=temp_p.getBytes("ISO8859-1");
String temp=new String(temp_t);
return temp;
}
catch(Exception e)
{
}
return "null";
}

|
在基于 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 ”; 

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

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

javac –encoding GBK。 

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

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

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

out.println(string);       // string 是含中文的字符串 

还是用 

,都必须作 UNICODE 到 GBK 的转换,或者手动,或者自动。在 JSP 1.0中,可以定义输出字符集,从而实现内码的自动转换。用法是 

 

但是在一些 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 字符集的操作系统和应用软件中就能够正确显示中文字符串 s2 。 

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

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

.CLASS 文件存放在服务器端,由客户端的浏览器运行 APPLET , APPLET 只起调入 FRAME 类等主程序的作用。界面包括 Textfield ,TextArea,List,Choice 等。 

I.       取中文 

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

将数据按“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); 

在转换字符串时不采用系统默认编码方式,而直接采用“ 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(dbbyte1,”iso-8859-1”); 

_stmt = _con.createStatement(); 

_stmt.executeUpdate(sqlstmt); 

…… 

问题:如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时(称为 A 情况),上述程序代码可正确执行。但是如果客户机只有浏览器,而没有 JDK 和 CLASSPATH 时(称为 B 情况),则汉字无法正确转换。 

我们的分析: 

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

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

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

2.如果在转换字符串时不采用系统缺省编码方式,而是直接采用 “GBK” 或“GB2312”,则在 A 情况下程序仍然可正常运行,在 B 情况下,系统出现错误: 

UnsupportedEncodingException。 

3.在客户机上,把 JDK 的 CLASSES.ZIP 解压后,放在另一个目录中, CLASSPATH 只包含该目录。然后一边逐步删除该目录中的 .CLASS 文件,另一边运行测试程序,最后发现在一千多个 CLASS 文件中,只有一个是必不可少的,该文件是: 

sun.io.CharToByteDoubleByte.class。 

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

4.在 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 可以帮助我们得到这些属性。 

类 PoorChinese 的源代码: 

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 中汉字编码的转化: 

  

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.err.println("Usage: jview gb2big5 gbfile big5file"); 

System.exit(1); 

   } 

String inputString = readInput(args[0]); 

writeOutput(inputString,args[1]); 

System.out.println("Number of Characters in file: "+iCharNum+"."); 



  

static void writeOutput(String str, String strOutFile) { 

try { 

FileOutputStream fos = new FileOutputStream(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); 

InputStreamReader 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         CharToByteBig5 

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(……) 

千万别忘了编译后放到 Servlet.jar 里面。 

五、 关于 Java 中文问题的总结 

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

                        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 applet里,怎么能只显示图像的一部分,比如只显示图片的中间一块?
  • java for web程序在浏览器显示阴影而不显示内容?
  • jbuilder7里如何在project pane里显示出某个project的所有的类的结构图,就如显示source java files的结构图一样
  • 谁能帮我一下100分:在PDA的WinCE平台上,用JAVA语言开发程序,为什么不能在label,button显示汉字呢?却能在textarea中显示汉字呢!!!
  • 在JSP页面中能否显示JB中的对话框或者JAVA应用程序?是在web页面内显示。谢谢高手指点
  • 请教高手:我编的Applet插件只显示一个灰影,在JAVA控制台显示:awt.graphics2d.class没找到 请问应如何解决??
  • 求解:为什么我写的Java程序不能显示中文。
  • 我的JAVA怎么不能显示中文呢?源程序如下......?
  • 我在JSP页面中调用一段显示打印对话框的Java程序,可是点击“打印”按钮后什么都不显示,请大伙帮忙指点一下!
  • 如何在IBM Visualage for java的编辑环境中显示汉字??谢谢!
  • java汉字显示乱码问题??
  • cmd中显示不了java程序中的中文字
  • Java程序的显示问题
  • 在JAVA中如何正确显示中文字体?
  • 在JAVA中如何正确显示中文字体?
  • 管道线程能够接收数据,然后显示异常:java.io.IOException:write end dead;
  • 管道线程能够接收数据,然后显示异常:java.io.IOException:write end dead;(紧急求救,急急急)
  • 请碰到过的哥们回应。Java GUI程序中如何设置显示字体呢?
  • 求救!!!JAVA中怎么显示WORD文档。
  • java的中文显示问题
  • linux环境下,java程序手工运行不乱码,crontab自动运行就乱码
  • java生成csv文件乱码的解决方法示例 java导出csv乱码
  • redhat7.3下,java程序打印中文直接用java命令执行正常,用crontab执行java命令为乱码
  • linux下java程序中的乱码问题
  • java中怎样解决汉字乱码问题?
  • java应用程序的中文乱码问题。
  • java DocConverter.jar转换word文档到pdf 中文乱码问题
  • java自动根据文件内容的编码来读取避免乱码
  • 用java读中文linux中的文件是正确的,用java读英文linux版本中的文件是乱码,如何使英文linux读出的文件数据也是中文的?
  • java通过stock与mysql通信时出现乱码的问题
  • java URL乱码的解决办法
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Java读写包括中文的txt文件时不同编码格式问题解决
  • 请教:关于英文,简体中文,繁体中文在JSP/JAVA中的整体解决方案!!!
  • 哪儿有较好的java中文资料与jbuilder的中文资料<我是一个新手>
  • 哪有java类库中文说明和jdk1.3.1的中文文档?
  • 请教:关于英文,简体中文,繁体中文在JSP/JAVA中的整体解决方案!!!!!
  • 在JAVA中如何将繁体中文和简体中文进行互相转换?
  • 在forte for java 4的Source Editor中编辑jsp时候,可以输入中文,可是保存后关闭再打开,中文显示???,怎么回事啊
  • Java简繁体中文互换 java-zhconverter
  • 请大家评价一下Thinking in Java第二版(中文)这本书如何,是否适合JAVA初学者?
  • 小弟我找到了一些JAVA认证模拟试题和JAVA中文FAQ,希望对大家有所帮助
  • Java国际化时怎么不能正确读取.properties文件中的中文字符串,如何解决其中的中文问题?
  • 请问哪里有java docs 的下载,中文版的,它是java的类库手册么?
  • 请问学习java比较好的中文书籍有哪些,谢谢!
  • 怎么是java程序支持中文?
  • 在实现简体中文转繁体中文,繁体中文转简体中文时,JAVA得如何实现???
  • 你认为最好的中文JAVA网站或有大量优秀JAVA源代码免费下载的网站是哪里???送分!!!
  • 请问:谁有中文的java1.3类库参考书???????????????
  • JAVA与中文问题???(中文出来就是乱码,换英文就正常)
  • 哪里可以下载到JAVA类库呀,最后有中文说明?
  • java 中中文编码问题 是不是 与本地系统有关?
  • 谁知道哪有JAVA的类库帮助啊!中文的!(在线给分)
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3