Java中文问题的一般解决办法

来源:互联网 发布:java怎么判断回文数 编辑:程序博客网 时间:2024/06/05 14:17

事实上, Java 的中文问题都是由于 Java 应用所采用的缺省编码格式与目标或者应用所要读入字符的编码格式不同而造成的(具体参见文献 1 )。对于如何解决 Java 的中文问题,通常有四种方法:

1 选择 JDK 的中文本地化版本。尽管 Java2 JDK 的中文本地化版本( http://java.sun.com/products/jdk/1.2/chinesejdk.html )并不是一个官方的版本, Sun 公司也没有承诺会对该本地化版本进行升级,但其仍不失为一个 Java 中文问题的解决方案。

2 选择合适的编译参数。对于 Java 的国际版本来讲,我们也可以在编译 Java 应用的时候通过指定确定的编码机制来实现其编译结果对中文的支持。例如,对于需要支持繁体中文和简体中文应用可以通过 javac -encoding big5 sourcefile.java javac -encoding gb2312 sourcefile.java 来编译源程序。

3 通过编程的方式实现字符编码的转换代码。通过编程的方式来解决 Java 的中文问题,已经成为了一种较为普遍的做法。下面就是一种最常见的字符编码转换函数,其将字符的编码格式转换为中文 Windows 系统的 GBK 编码形式。

public static String toChinese(String strvalue)

   {

         try{

             if(strvalue==null)

                return null;

             else

             {

                strvalue = new String(strvalue.getBytes("ISO8859_1"), "GBK");

                return strvalue;

         }

         }catch(Exception e){

               return null;

         }

   }

  

 

4 定义字符输出集。对于 JSP 应用,我们可以通过 <%@ page contentType="text/html; charset=GBK" %> <%@ page contentType="text/html; charset=GB2312" %> 来定义 JSP 页面的字符输出集。当然,我们也可以通过 HTML 的标记 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312"> 来定义字符的输出集。

 

存在的问题

根据方法实现的方式,我们可以将以上四种方法分为两类,一类是通过利用某些标准或者规则来实现的方法,上面的 1) 2) 4 )都属于此类;一类是通过针对性的编程来实现的方法,上面所提的方法 3 )就属于此类。

由于方法 1) 2) 4 )是具有规范性的一类方法,所以方法比较简单,解决方案也不具备较大的针对性,较为通用,例如我们可以采用方法 2 )的编译方式通过编译 Java 源文件来实现内码的预置,而无需考虑源码到底有哪些部分出现了 Java 的中文处理问题,诸如输出乱码等等。

但是,正由于这些方法不具备针对性,解决问题的方法过于统一,所以在某些情况下,它们并不能彻底地解决 Java 的中文问题。举一个非常常见的例子。在通常情况下,用户的 Java 应用往往需要与其它 Java 应用接口进行交互,例如通过某种版本的 JDBC 访问数据库。由于 JDBC 的驱动所支持的编码随着提供商乃至版本的不同而不同,所以如果在数据库的输入输出过程中出现中文不能正确处理问题时,我们需要在数据的输入和输出过程做两次正好相反的编码转换,这对于方法 1 ), 2 ), 4 )来说,往往是无法解决的。当然,对于方法 2 ,我们也可以通过采用一些技巧使来满足上面的情况,一个最有效的办法就是尽量将 Java 应用的各个部分组件化。例如我们可以通过将数据库的读入和输出代码分解在不同的源文件上来实现分别编译,从而满足不同的字符编码要求。但是通常的程序设计都不太可能满足这种要求,因为这种程序的划分结果很可能是不合理的。例如,我们将数据库的读出和写入方法封装到一个类中是比较合适的一种设计,但如果将该类的这两个方法分别实现在两个文件里则变得非常不合理。因此对于 1 ), 2 ), 4 )方法来说,虽然实现比较简单,但却具有一些无法克服的缺点。这也是那些实现起来相对复杂的编程方法得以流行的原因。

相对于方法 1 ), 2 ), 4 )来说,方法 3 )具有更好的针对性和灵活性。程序可以根据不同的情况做出灵活的处理,在任何需要的地方进行字符的编码转换,但是该方法的特点也对软件的开发人员提出了更高要求 -- 必须能够准确的捕捉到有可能发生中文处理问题的地方,并做出正确的判断和处理。

 

 

分析的原则

总的说来,所有解决 Java 中文处理的方法都不是很复杂。相反的是,由于 Java 技术特别是 J2EE 技术涉及的内容繁多,各种 Web 服务器、应用服务器以及 JDBC 数据库驱动等参差不齐,所以如何正确而及时的发现应用的中文处理问题则变得相对复杂的多。那么我们如何来发现这些问题呢?

通常, Java 处理中文时所产生的问题都是由于用户的 Java 应用所采用的缺省编码格式与目标或者应用所要读入字符的编码格式不同而造成的,而引起这些不同的一个主要原因就是用户的 Java 应用与其它应用进行了编码格式不匹配的数据交换(包括直接或间接的数据输入、输出)。所以,为了及时发现问题,我们可以由这一点入手,根据以下的原则对应用进行分析:

1.      注意字符变量情况 。由于变量的字符编码形式较为隐蔽,多次变量间数值的改变和运算可能会引起字符集的改变;在变量与页面所提交数据的各种操作中,较容易发生不同编码格式字符进行运算的情况。

2.      注意任何形式的字符读入与输出 。之所以要提到任何形式,是因为 Java 应用大多数都是作为网络应用开发的,所以与其它语言的应用相比, Java 应用需要面对网络世界各种各样的字符数据交换形式。例如各种表单的数据提交, URL 形式的数据读入,经过加密运算的字符数据交换,网页控件选择结果的输入,控件内容的的显示(如 List 控件)等等。

3.      小心使用第三方的组件和应用 。由于第三方组件和应用的实现是非透明的,所以一般情况下,我们很难判断这些组件或驱动的缺省编码格式是什么,也无法对其进行控制。因此,在使用它们所提供的接口函数进行数据交换的时候要特别注意,如果确实出现中文无法正确处理情况,应首先检查我们自己的代码并调整相关代码以适应这些接口,因为这些组件或者应用基本上不会提供调整编码机制的接口。必要时,我们可能需要采用其它可替换的组件或者应用。

4.      注意被请求对象所含有的数据输入与输出 。这是非常隐蔽的一类情况,当我们的应用以对象的方式(例如序列化的对象)进行交互时,如果这个对象内部含有字符数据的处理过程,或者含有某些数据的输入、输出,甚至是抛出一段用中文注解的异常,都可能出现中文无法正确显示等问题。由于这些行为往往被封装在对象中,所以我们在编写程序时,很容易忽略这种可能情况。并且这种情况带有一定的不可预见性,例如我们可能不清楚这个对象会在什么时候抛出什么样的异常,所以这时我们就需要做一定的测试工作。

5.      注意数据库的数据访问过程 Java 通过 JDBC 与数据库建立连接。对于 JDBC 驱动程序来说,由于目前大部分的 JDBC 驱动程序并不是针对中文系统而设计的 ( 中文数据大都采用 ISO-8859-1 编码方式 ) ,所以一般情况下在数据读写过程中往往都需要字符编码的转化。但是我们仍建议用户在使用这些 JDBC 驱动时,仔细阅读它的说明。如果确实无法弄清 JDBC 字符数据的编码到底是什么,我们的建议是做一些必要的测试。例如下面是一组在简体中文 Win2000 平台下,采用 Weblogic 6.0 所提供的 JDBC 驱动从 MS SQL Server2000 中正确读入中文字符的代码(例子中进行了字符运算):

         ...

Class.forName("weblogic.jdbc.mssqlserver4.Driver").newInstance();

           conn = myDriver.connect("jdbc:weblogic:mssqlserver4", props);

      conn.setCatalog("labmanager");

     Statement st = conn.createStatement();

                 //execute a query

         String  testStr;

String testTempStr = new String() ;

          testStr = new String(testTempStr.getBytes("ISO-8859-1"));// 编码转化

         DatabaseMetaData DBMetaData =conn.getMetaData();

                 ResultSet rs = DBMetaData.getTables(null, null,null,new String[]{"TABLE"} );

                 while (rs.next()){

                          for(int j=1; j<=rs.getMetaData().getColumnCount(); j++){

testStr = testStr +String(rs.getObject(j).toString().getBytes("ISO-8859-1"));

                          }

                 }

                

6.       

7.      然而,需要注意的是,不同的 JDBC 驱动对相同的数据库的支持并不同,而同一类 JDBC 驱动对不同的数据库的支持也不相同,也就是说我们的字符转化代码在 JDBC 驱动改变甚至是版本变化情况下都有可能无法正确工作。例如对于上面的例子,在同样的环境下改用 i-net Una 2000 Driver Version 2.03 for MS SQL Server 时,是无法正确处理中文的。原因很简单,这个 JDBC 驱动本身支持的就是 GBK 的编码机制,所以根本就不需要做任何的编码转化。

6 必要的测试 。由于 Java 中文问题的产生随着 Web 服务器,浏览器,运行环境和开发工具的不同都可能发生变化,所以为了更好的避免问题的发生,我们必须作一些针对性的测试。另外,在我们确实无法通过分析来确定 Java 的中文处理问题是否可能发生的情况下或者无法知道问题的发生是由于哪个环节(是 Web 服务器,浏览器还是 JDBC 数据驱动等等)引起的时候,测试工作则变得非常重要。并且我们可能需要较为全面的测试,例如对 Web 服务器,浏览器和 JDBC 数据驱动等都要做测试,这样有利于我们找出那些隐藏在多个环节协调过程中所产生的问题。

原创粉丝点击