首页 > 编程知识 正文

eclipse java中文乱码,java中文乱码解决

时间:2023-05-05 08:22:20 阅读:225151 作者:1135

最近进行RAC迁移,将US7ASCII编码的RAC替换成UTF-8编码的单点ORACLE,迁移后发现Java从新库读到的中文是乱码,这引发了我的考虑:
        1、Java为GBK,Oracle为ISO-8859-1时,Java读Oracle得到的中文是否会乱码?如何转码?
        2、Java为GBK ,Oracle为UTF-8时,Java读Oracle得到的中文是否会乱码?如何转码?
        结论让我很诧异,居然是:
        1、会乱码,需要通过newString (s.getByte(“ISO-8859-1”,”gbk”)进行转码
        2、不会乱码。
一、不需要转码的原因         其实,无论Java、Oracle采用何种编码,在Java读Oracle都是不需要显式转码的。转码动作的动作会由Oracle驱动自动完成。确切地说,这还不算是转码,而只是解码。Oracle驱动仅仅是根据数据库定义的字符集,把读到的字节流解码成字符。
        既然如此,那么为什么在第一种情况下我们还需要进行转码呢?
        原因其实很简单,那就是RAC上保存内容的编码和它声称的不一致。RAC声称是US7ASCII(ISO-8859-1)的,但实际保存的内容却是GBK的。
        由此我忽然想到,PL/SQL Devoloper真的很强大,在RAC这种保存内容的编码和声称不一致的情况下,Devoloper居然还能正确显示中文。不知道它是不是对US7ASCII类型的数据库做了特殊处理。
二、转码方法         当Java读Oracle遇到中文乱码时,我们就需要进行转码。转码的方法很多,我接触过的有以下几种。
1、纯手工转码         将读到的字符串s进行转码,如:new String(s.getByte(A), B)
2、Druid         druid是阿里巴巴自己开发的一个驱动,它其实是对各种数据库驱动做了一层统一的封装,添加日志、告警、编码转换等功能。配置方式如下: <bean id="opensqlDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="com.alibaba.china.jdbc.SimpleDriver" /><property name="url" value="jdbc:oracle:thin:@10.20.130.210:1521:dwtest" /><property name="username" value="etl" /><property name="password" value="etl" /><property name="connectionProperties"><value>serverEncoding=ISO-8859-1;clientEncoding=GBK;defaultRowPrefetch=50;bigStringTryClob=true</value></property></bean>        其中connectionProperties中包含serverEncoding、clientEncoding两个属性。在Java读取到数据后,如果发现serverEncoding、clientEncoding不同,则会自动进行如下编码转换。
new String(s.getByte(serverEncoding), clientEncoding) 3、weblade ibatis callback         部门同事之前开发过一个二方库,它采用了如下注册ibatis callback的方式。 <bean id="sqlMapExecutorDelegate"class="com.asc.alibaba.dao.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate"><property name="mappedStatementStrategy" ref="mappedStatementStrategy" /><property name="handlerList"><list><ref bean="stringHandler" /><!-- <ref bean="objectHandler" />--></list></property></bean><bean id="stringHandler" class="com.asc.alibaba.dao.ibatis.handler.TypeHandlerAdapter"><property name="javaType" value="java.lang.String" /><property name="handlerCallback" ref="stringTypeHandlerCallback" /></bean>         使得在默认情况下,程序会把ibatis获取到的String进行如下编码转换: new String(s.getByte(“ISO-8859-1”), “GBK”)         该二方库引入的方式如下:
<dependency><groupId>com.alibaba.asc.shared</groupId><artifactId>weblade.core.ibatisext</artifactId><version>1.2.0-SNAPSHOT</version></dependency>         Ibatis callback隐藏了编码转换的过程,但问题是它对项目中所有的数据源生效。使得无法同时透明地支持需要转码和无需转码的数据源。
三、RAC迁移         RAC迁移的目标是要将US7ASCII编码的RAC换成UTF-8的ORACLE库IDATA,其中RAC中实际保存的内容是GBK。我接触过的RAC迁移包含如下项目。
1、websql         原方案没有用任何第三方工具,直接采用纯手工转码。因此RAC迁移很简单,新方案只要针对新库不做转码即可。
2、傻瓜平台         原方案是使用druid转码,其中 serverEncoding=ISO-8859-1;clientEncoding=GBK         新方案是直接删除connectionProperties中的serverEncoding、clientEncoding,或者直接将它们改成相同值。
3、Ipage&task         原方案是使用了weblade ibatis callback。
        新方案1是覆写ibatis callback,对不同数据源做不同处理,使得在新库上不做转码。
        新方案2是在新datasource上使用druid,并进行如下配置: serverEncoding=GBK,clientEncoding=ISO-8859-1         目的是在从db获取到数据后,先做一次GBK ==> ISO-8859-1的转码,然后让weblade中的callback再做一次ISO-8859-1 ==> GBK的转码。
个人倾向于第2种方案。
        不过,大家考虑一下,新方案2真的可行吗?会不会由于丢失信息而导致中文乱码?


版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。