中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Java > J2SE
Java数据库字符国际化
作者:未知 时间:2005-07-24 21:13 出处:JR 责编:chinaitpower
              摘要:Java数据库字符国际化
数据库字符国际化是大家提问最多的问题,例如MySQL数据库大家可能在JDBC-URL添加useUnicode=true&CharacterEncoding=GBK作为中文支持的基本条件。但这有时破坏了数据的完整性,如果某些人粗心大意,就会导致数据编码错误,产生乱码。因此,我们需要一些手段在程序内部进行编码处理。人们一般通过在应用上使用 String(bytes:byte[], enc:String)/String.getBytes(enc:String)进行字符串编解码,这样做虽然易懂,但是如果遇到大字段表格,手动编码时费时费力。

我的方法:通过研究JDK类库,可以感觉到多层处理机制在数据处理上的优越性。我们完全有可能在数据库上建立一个中间层用于字符的国际化处理,我就是这么做的。仔细研究一下JDBC操作数据库出现字符编码问题的根源,很容易发现多数情况是ResultSet的几个String方法在作怪,因此我们就完全可以编写一个ResultSet中间层进行国际化处理,源码如下:
  1. public class I18nResultSet implements ResultSet{
  2.   private String encoding;
  3.   private ResultSet rs;
  4.   public I18nResultSet(ResultSet rs, String encoding) throws java.io.UnsupportedEncodingException{
  5.     //检查该编码名称是否被系统支持。
  6.     "".getBytes(encoding);
  7.     this.rs = rs;
  8.     this.encoding = encoding;
  9.   }
  10.   … …
  11.   //以下几个方法是进行String字符串的重编码.
  12.   public String getString(int index) throws SQLException{
  13.     String data = null;
  14.     try{
  15.       data = new String(rs.getBytes(index), encoding);
  16.     }catch(java.io.UnsupportedEncodingException uee){}
  17.   }
  18.   public String getString(Stirng field) throws SQLException{
  19.     String data = null;
  20.     try{
  21.       data = new String(rs.getBytes(field), encoding);
  22.     }catch(java.io.UnsupportedEncodingException uee){}
  23.   }
  24.   public void updateString(int index, String value) throws SQLException{
  25.     try{
  26.       rs.updateBytes(index, value.getBytes(encoding));
  27.     }catch(java.io.UnsupportedEncodingException uee){}
  28.   }
  29.   public void updateString(String field, String value) throws SQLException{
  30.     try{
  31.       rs.updateBytes(field, value.getBytes(encoding));
  32.     }catch(java.io.UnsupportedEncodingException uee){}
  33.   }
  34.   … …
  35. }


可以看出, 所有的String操作都使用特定编码的字节数组进行存取,这样通过定义encoding的值实现数据库存取数据编码的一致性,且encoding完全可以通过在配置信息中动态定义。

同时,上面的程序又可以解决一些固有的字符串处理问题,例如控制符如\r\n导入到数据库中很有可能被解析为\\r\\n使其不能换行,通过字节数组操作,就可以解决这个问题。这样像文章固有格式就可以完整地保留下来而不需要进行额外转换操作。

结论,通过多层处理机制使用中间层对数据库数据进行层层处理可使处理环节之间形成松耦合关系,从而可以进行有效的控制。

下面给一个使用动态代理进行字符控制的代码(原创):
  1. package com.yipsilon.crocodile.database;
  2. import java.sql.ResultSet;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Method;
  5. import java.io.UnsupportedEncodingException;
  6. /**
  7.  * 作者 yipsilon
  8.  * 如要转载, 请通知作者
  9.  */
  10. public class I18nResultSetHandler implements InvocationHandler{
  11.   private ResultSet rs;
  12.   private String encoding;
  13.   public I18nResultSetHandler(ResultSet rs, String encoding) throws UnsupportedEncodingException{
  14.     this.rs = rs;
  15.     "".getBytes(encoding);
  16.     this.encoding = encoding;
  17.   }
  18.   public Object invoke(Object proxy, Method method, Object[] args)
  19.       throws Throwable{
  20.     String methodName = method.getName();
  21.     if(methodName.equals("getString")){
  22.       Object obj = args[0];
  23.       if(obj instanceof Integer){
  24.         return decodeString(rs.getBytes(((Integer)obj).intValue()), encoding);
  25.       }else{
  26.         return decodeString(rs.getBytes((String)obj), encoding);
  27.       }
  28.     }else if(methodName.equals("updateString")){
  29.       Object obj = args[0];
  30.       if(obj instanceof Integer){
  31.         rs.updateBytes(((Integer)obj).intValue(), encodeString((String)args[1], encoding));
  32.       }else{
  33.         rs.updateBytes((String)obj, encodeString((String)args[1], encoding));
  34.       }
  35.       return null;
  36.     }
  37.     return method.invoke(rs, args);
  38.   }
  39.   private String decodeString(byte[] bytes, String enc){
  40.     try{
  41.       return new String(bytes, enc);
  42.     } catch(UnsupportedEncodingException uee){
  43.       return new String(bytes);
  44.     }
  45.   }
  46.   private byte[] encodeString(String str, String enc){
  47.     try{
  48.       return str.getBytes(enc);
  49.     } catch(UnsupportedEncodingException uee){
  50.       return str.getBytes();
  51.     }
  52.   }
  53. }


使用时调用: 
  1. ResultSet rs = ... ; //原始的ResultSet结果集
  2. String encoding = "GBK"//字符编码
  3. (ResultSet)Proxy.newProxyInstance(rs.getClass().getClassLoader(),
  4.                               rs.getClass().getInterfaces(),
  5.                               new I18nResultSetHandler(rs, encoding));


如有问题请Email(yipsilon@163.com)或者使用QQ(31482617)联系我。
关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有