快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

关于Java中文问题的几条分析原则

 
引言

尽管对于Java中文处理问题的讨论已不乏其数,但由于Java技术涉及内容广(J2EE包含了十几种相关技术),技术供给商繁多,面向Java的Web服务器、应用服务器以及JDBC数据库驱动等都没有官方的标准,所以Java应用在处理中文过程中出了存在固有的问题外也存在随着选用的服务器,驱动程序的不同而带来的Java中文问题的多变性,增加了问题的复杂度。那么,我们如何在这么纷繁的现象中找到问题的症结呢?

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

事实上,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\")); } }

    然而,需要注重的是,不同的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数据驱动等都要做测试,这样有利于我们找出那些隐藏在多个环节协调过程中所产生的问题。

结论

事实上,Java中文处理之所以存在问题,其根本原因是由于被操作的中文字符(变量)的编码格式与目标的编码格式不同造成的,所有这些问题其实都是发生在字符的读入、输出过程中的,只要我们掌握住这一环节,就可以更好的发现、分析、处理和防备Java的中文问题了。






返回类别: 教程
上一教程: 我了解的javaIDE浅析
下一教程: java中找到资源文件的路径

您可以阅读与"关于Java中文问题的几条分析原则"相关的教程:
· Java 中文问题的解决
· Java 关于中文乱码问题的解决方案与经验
· java 与 mysql 中文问题的处理
· Java 关于中文乱码问题的解决方案与经验 (2)
· 关于JDK1.2的JDBC中文问题的解决
    微笑服务 优质保证 索取样品