您的位置:首页 > 编程语言 > Java开发

mysql +java 中文乱码问题彻底理解和解决

2010-10-15 17:42 736 查看
转 : http://student.csdn.net/space.php?uid=14032&do=blog&id=36249

在它的基础上我又总结了一下。

如果你用客户端(如EMS)输入的测试中文文字  也必须保证编码格式为utf-8。

我就是因为这个问题 频繁的用客户端进行的添加 所以没有找到根本问题。定要保证所有的编码格式是一样的。

再此感谢这位写博客的人。3个小时不白费。

 

|  1 | ????MySQL???????? |
|  2 | ??MySQL??         |
|  3 | 测试MySQL编码     |
+----+-------------------+
现在可以看到中文正常显示了(主要是因为utf8也支持中文),所以当我们使用命令行工具连接数据库的时候最好将客户端的编码改一下,如果使用GUI的话就不必了,同时修改客户端的编码之后程序依然能够正常显示(以上两点已经测试)

所以如果在程序中要显示中文的话我们可以选用utf8,gb2312,gbk这三种编码,但是如果想在命令行添加中文数据或者查看的话就需要将客户端的编码设置为gb2312或gbk了,还是那句,CMD的编码有关

Code:
对初学者来说,java与MySQL的连接以及MySQL的中文乱码问题是两个比较头疼的问题。我刚做了一个小项目,对这两个问题也是绞尽脑汁,也是初学者,花了一番功夫去查网页,找答案。作为一个初学者,我也完全以初学者的立场叙述一下我遇到的问题以及其解决的方法。也望能给刚陷入次困境的朋友有些许帮助!
我用的版本:
JDK:j2sdk1.5.0
MySQL:mysql-5.0.41-win32_178
JDBC驱动:mysql-connector-java-3.2.0-alpha-bin.jar

一、java与数据库的连接
java与数据库的连接书上写有四种方法,我的理解其实从其实质上说就两种,一种建立JDBC-ODBC桥,通过ODBC数据源与数据库相连。另一种是纯java式的连接,通过java类库API驱动连接。以MySQL为例,这两种方法分别需要MySQL-ODBC驱动和MySQL-JDBC-ODBC驱动。我用的是第二种方法,当然也建议使用纯java式的连接,需要MySQL-JDBC-ODBC驱动,可以从网上下载。
首先需要把驱动放在jdk的安装目录的lib目录中,并在环境变量classpath中加上该jar包,其设置和jdk的classpath中dt.jar和tools.jar一样。
连接过程分三步:加载驱动程序;使用java.sql包中的Connection建立连接;由Connection对象产生Statement对象,然后Statement对象就可以调用其方法传递SQL语句了。
下面以一个具体的实例来测试我们的连接:

import java.sql.*;
public class ConnectToMySQLTest
{
public static void main(String[] args)
{
try
{
//加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
//创建指定数据库的URL
String url="jdbc:mysql://localhost:3306/student"; //student是创建的数据库的名字
String userName="root"; //root是MySQL默认的用户名
String password="123"; //123是你设置的MySQL密码
//创建连接
Connection conn=DriverManager.getConnection(url,userName,password);
//创建Statement对象
Statement stmt=conn.createStatement();
//Statement对象向数据库提交SQL语句
stmt.execute("drop table if exists stu"); //若表stu存在则删除
stmt.execute("create table stu(id int not null primary key,name varchar(20) not null,sex varchar(4))"); //创建表stu
//插入记录
stmt.execute("insert into stu values(1,'aaa','boy')");
stmt.execute("insert into stu values(2,'bbb','girl')");
stmt.execute("insert into stu values(3,'ccc','girl')");
//执行查询数据库操作,并返回查询的结果集
ResultSet rs=stmt.executeQuery("select * from stu");
//将结果集表指针定位到第一条记录前
rs.beforeFirst();
//打印查询结果
System.out.println("stu表的数据如下:");
System.out.println("---------------------");
System.out.println("学号/t姓名/t性别");
System.out.println("---------------------");
int num;
String name;
String sex;
while (rs.next())
{
num=rs.getInt("id");
name=rs.getString("name");
sex=rs.getString("sex");
System.out.println(num+"/t"+name+"/t"+sex);
}
stmt.close();
conn.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

在测试之前,你需要启动MySQL,在mysql命令窗口中输入:create database student; 回车建立student数据库,然后在命令提示符中编译运行ConnectToMySQLTest,即可出现如下结果:

二、MySQL中文乱码问题
首先我们先来做个测试:
上面的代码运行成功后,打开mysql命令窗口,在其中输入:use student; (回车选择数据库)
select * from stu; (回车出现如下查询结果)

然后把上面代码stmt.execute("insert into stu values(1,'aaa','boy')");中的'aaa'改为'张三',然后保存重新编译运行,运行的结果为:

我们再打开mysql命令窗口,因为刚才我们已经选择了student数据库,我们可以直接输入:select * from stu; (回车查询) 结果如下:

可以发现改成张三以后,运行结果正常显示,但mysql中却显示的是两个问号。

MySQL默认的字符编码是latin1,与java对应的就是ISO-8859-1。所以要正确的显示我们的中文字符,只需要将MySQL的字符编码方式有latin1改成中文的就行了,改成“gbk”或"gb2312",修改的方法有两种:
一种是重新配置MySQL,在它的配置向导中有一项是让你选择字符的编码,你可以选择自定义选项,然后将其自定义为“gbk”或“gb2312”;
另一种是直接修改MySQL安装目录中的“my.ini”文件,在MySQL的安装目录下找到该文件,用记事本打开,在其中找到以下两句:
[my sql]
default-character-set=latin1

[my sqld]
……
……
default-character-set=latin1
分别将其中的latin1改成“gbk”即可,注意要用小写,听说大写不识别。

网上还有几种其他的方法,在这里也说一下,有一种是在连接数据的连接串中指定字符集和Unicode编码,他把数据库的URL写成:
String url="jdbc:mysql://localhost:3306/student?user=root&password=123&useUnicode=true&characterEncoding=gb2312";
这样写的目的是告诉驱动在与数据库进行转码的时候按照这种方式来转,从而避免乱码,这种方法只能解决从java从MySQL中取出数据输出时的乱码问题,但若从java中向MySQL中插入中文数据时,在MySQL中仍然显示的是乱码,因为你并没有修改MySQL的字符编码方式,它还是默认的latin1,所以中文仍然不能正常显示,换句话也就是说,若MySQL的编码方式是latin1,你java向其中插入中文时,在MySQL中永远是乱码,它只能正确显示在MySQL中直接向其插入的中文,从外界向其插入中文它是不能正常显示的。

还有一种方法是,再使java从MySQL中取出数据时让其由"latin1"转化为"gbk",从java向MySQL中插入数据时让其由"gbk"转化为"latin1",以取出数据为例,经过这样的转化:

String name=new String(rst.getString("name").getBytes("ISO-8859-1"),"GBK");

这里注意:gbk在java中是大写,小写会出错。latin1在java中对应的是ISO-8859-1.

也可以写两个转化函数,在转化时通过调用函数去转化,这两个函数如下:
import java.io.UnsupportedEncodingException;
//解决中文问题
public class EncodingUtil {

//从数据库取出用
public static String latin1ToGBK(String str)
{
try {
String temp_p = str;
byte[] temp_t = temp_p.getBytes("ISO-8859-1");
String temp = new String(temp_t,"GBK");
return temp;
}catch (UnsupportedEncodingException ex) {
System.out.println(ex);
return "";
}

}

//存入中文数据时用
public static String GBKToLatin1(String str)
{
if(str==null)
{
str="";
}
else{
try{
str=new String(str.getBytes("GBK"),"ISO-8859-1");
}
catch(Exception ex){
ex.printStackTrace();
}
}
return str;
}
}

但这种用于较少的数据库操作的话还行,若你要频繁的从数据库中存取数据,那么每一句存取的语句你都去调用方法去转化,那显然是行不通的。

写到这里,我再多说一点,我自己的理解对于后两种方法,应该是在早期驱动程序不完善的时候出现问题的解决方法,可能驱动程序中对两种编码的转化没有能很好的实现,从而导致的存取乱码问题,我在网上就见过有人通过修改mysql-jdbc驱动去解决问题,因为mysql-jdbc驱动是开放源码的,他通过修改程序,重新编译生成class文件,然后运行不出现任何问题,很牛的人。
我自己的理解认为:现在的驱动已经完善了,所以在存取数据库时,不会出现乱码问题,乱码问题只是数据库使用的编码方式若不是中文的,那么在向其插入中文数据时,它不能正确显示出来,我们只需修改数据库的编码方式即可OK了。

还有注意:不同版本的MySQL会有不同的结果,这个很奇怪,网上有人说MySQL数据库的东西都是二进制存放的,支持任何数据,当然包括中文,你在MySQL命令行下输入:
insert into stu values(4,'李四','boy');
select * from stu;
会正确显示李四,而如果你在java中向其插入该条记录,再在MySQL中查看,就成??了,他的意思是证明了乱码出现的原因是在java与MySQL的连接部分,也即驱动不能正确转化。我在mysql-5.0.51a-win32中这样测试过,确实是这样的,但你在我们现在用的mysql-5.0.41-win32_178中测试,若MySQL编码为latin1时,在MySQL命令中插入中文记录时,会出现错误:ERROR:1366(HY000)Incorrect string value: .....
也即在mysql-5.0.41-win32_178中,若编码为latin1时,它不让我们直接插入中文数据,但不知为何在mysql-5.0.51a-win32却可以,这是个疑问,有知人士可以给出解答,在这先谢了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐