今天和甲方数据对接时,使用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 block
e.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数据库的,也就是说最开始的转码方法并没有错,只是因为可视化工具的原因导致的乱码错误,这浪费了美琴大半天,有时真的是一个小小的错误就能找半天呢。