今天和甲方数据对接时,使用JAVA程序上传数据到Oracle数据库,上传的数据出现乱码,这是由于编码不同引发的错误。美琴的项目使用的编码是UTF-8,而对方的Oracle数据库编码为US7ASCII。
查询Oracle数据库编码
select * from nls_database_parameters where parameter =’NLS_CHARACTERSET’;
双方编码不同导致数据上传到Oracle库中文显示乱码,USASCII是标准的ASCII码,只能存单字节,而中文在UTF-8中都是以双字节或三字节存储的,而且UTF-8是高位字节码,ASCII是低位字节码,二者转换就会导致数据丢失,所以要使用中间码ISO-8859-1来转换,ISO-8859-1是ASCII的父集,可以完好的保存ASCII数据。
JAVA进行转码
String s = "美琴";
String o = new String(s.getBytes("UTF-8"),"ISO-8859-1");
//此时的o就是美琴转为ISO-8859-1码的内容
因为美琴要将一个SQL整个转码,所以美琴当时是写了一个工具类来封装,每次有需要转码的就调用该方法进行转码,之后运行程序,执行SQL,打开Oracle库查看数据,发现Oracle数据库存入的数据都是一堆???。这把美琴急坏了,又去寻找其他的方法试图修改,并写测试类进行转码,经过大半天的测试,一点办法都没有,上传的数据还是???。
因为美琴技术比较菜,不懂就问嘛,所以就去请教同事,他们给予了我很多灵感,包括SQL拼接ASCIISTR函数(该方法会把值存成ASCII类型),转16进制函数,还有修改数据库字段为nvarchar2(该类型不会管数据库编码,是什么内容就存入什么内容),以及每个字段都进行转码,种种方法,都试过了,之后同事过来写了测试类帮忙测试。终于发现了问题!
这是获取数据库连接的方法
public static Connection getConnection() {Connection connection = null;// 创建一个数据库连接try {System.out.println("开始尝试连接数据库!");String url = "jdbc:oracle:thin:@10.18.0.***:1521:orcl";//Oracle的默认数据库名String user = "****";// 系统默认的用户名String password = "****";// 安装时设置的密码connection = DriverManager.getConnection(url, user, password);// 获取连接System.out.println(url);System.out.println("用户名:" + user + "\t" + "密码:******");System.out.println("数据库连接成功!");return connection;} catch (Exception e) {e.printStackTrace();return null;}}
这是调用上次数据的方法
public static int insert() {Connection conn=getConnection();PreparedStatement ps=null;ResultSet rs=null;String sql="insert into TEST2(ID,NAME) VALUES (?,?)";try {ps=conn.prepareStatement(sql);String name = "张三";String id = "电话";//对sql中的第x号位给予值ps.setString(1,new String(id.getBytes("utf-8"),"iso-8859-1"));ps.setString(2,new String(name.getBytes("utf-8"),"iso-8859-1"));ps.setString(2,name);ps.setString(1,id);return ps.executeUpdate();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}
这是获取值得方法
public static List<Object> queryAll() {Connection conn=getConnection();PreparedStatement ps=null;List<Object> list=new ArrayList<Object>();try {String sql = "select * from \"TEST\"";ps=conn.prepareStatement(sql);ResultSet rs=ps.executeQuery();rs=ps.executeQuery();while(rs.next()) {//获取对应字段的值String userName =new String(rs.getString("NAME").getBytes("iso-8859-1"),"utf-8");String address = new String(rs.getString("ADDRESS").getBytes("iso-8859-1"),"utf-8");System.out.println("");}} catch (Exception e) {System.out.println("多条查询中创建PrepareStatement失败");e.printStackTrace();}finally {try {ps.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}return list;}
美琴发现乱码取出来的值竟然是中文!!!美琴是使用Navicat查看Oracle数据库的,也就是说最开始的转码方法并没有错,只是因为可视化工具的原因导致的乱码错误,这浪费了美琴大半天,有时真的是一个小小的错误就能找半天呢。