前两天项目中遇到mysql乱码的问题,折腾了好几天,查了好多资料,最后在恍然大悟中解决了。今天先简单的说说这个事,然后把在这个事中查找学习到的心得记录下来,以与大家分享,亦备后用。
一.我把所有页面,所有请求都编码都统一用utf-8,使用Filter过滤所有request和response都设成utf-8,数据库character_set_database设置utf-8,我知道character_set_client还是默认的latin1但是我在连接数据库时url后面转码了:
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true。
结果问题依旧!哪怕我在代码中用jdbc直接insert into 表 values(中文),在数据库中client用select查询都是乱码,用jdbc查出来打印到日志上是乱码,显示到页面上还是乱码。从数据的"行走"路径看,编码格式都是统一的,应该没有问题,抓狂!难道是url设置的转码没起作用?难道是tomcat对请求自动设置了其它编码?难道跟linux操作系统编码有关?第一种情况最有可能,我找到管服务器的人员,要求修改character_set_client=utf8,结果吃了闭门羹:公司数据库设置都是统一的,不能随便修改;况且以前项目使用的数据库也是这样的设置,可以在程序中解决乱码。对于第二个问题,也是公司服务器上的tomcat,我知道会得到什么回答了,也就不再自讨没趣。对于第三问题,从页面输入和显示的数据,应该跟操作系统没有关系吧,再说了这个改起来更费劲,只是做个参考。继续抓狂!静下心来,从我在代码中用jdbc直接insert into 表 values(中文)这个测试看,跟web传输过程中的编码没有关系,我决定把问题锁定在建立连接时转码问题。又仔细查了几遍,发现我在使用Proxool建立连接池时使用的是properties文件,而原有项目使用的是xml文件,恍然大悟,转码方式不能照搬!于是把
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
中的amp;全部去掉,重试,页面上出现了笑容灿烂的汉字。高兴!
二.为了这么个简单的问题,查阅了大量资料,从结果上看,并没有直接上用的,可是感觉收获颇多,相信对jsp和mysql乱码的问题又有了进一步的认识。
1.mysql中关于字符集的种类有很多,对我们编程有影响的主要是客户端字符集(character_set_client)和数据库字符集(character_set_database)在写入时Mysq会将客户端指定的字符集转换成数据库字符集存入数据文件,读取时又将数据库字符集转换成客户端指定的字符集展示给客户端,把客户端字符集和数据库字符设置一致,显而易见的好处是免掉转换的性能损耗;另外,如果考虑到以后数据库的迁移,将数据库字符集设置为大多数数据库都支持的字符集会省掉很×××烦。
1>.客户端字符集的设置有这么几种方法:
A. 使用控制台连接,在my.ini文件中的client项里面设置;
B. 使用ems连接,优先使用ems连接配置的字符集,默认使用my.ini文件中的设置;
C. jdbc连接,在连接串中指定:
jdbc:mysql://192.168.0.10:3306/test?useUnicode=true&characterEncoding=utf-8
2>.几个有关mysql命令行字符集相关的命令
A. 查看 MySQL 数据库服务器字符集,数据库字符集和客户端字符集
show variables like '%char%';
+--------------------------+----------------------------------------+
| character_set_client | latin1 | 客户端字符集
| character_set_connection | latin1 |
| character_set_database | utf8 | 数据库字符集
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 | 服务器字符集
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
B. 查看 MySQL 数据表(table) 的字符集
show table status from tablename like '%countries%';
C. 查看 MySQL 数据列(column)的字符集。
show full columns from tablename;
D. 查看当前安装的 MySQL 所支持的字符集。
show char set;
2.我们对数据库的操作无非就是存取数据,在这一过程中,乱不乱码和数据库字符集好像没有什么关系。我们只要保证写入时选择的字符集和读取时选择的字符集一致,即只需保证两次操作的客户端字符集一致并且该字符集支持所存取的数据字符即可.
三.顺次看常见jsp乱码及解决方案:
1.架设服务器安装MYSQL时的会让你选择一种编码,如果这种编码与你的网页不一致,可能就会造成JSP页面乱码.
解决方案:如果安装mysql的编码已不能更改,很多朋友是购买虚拟主机建立网站,无权更改MYSQL的安装编码,这一关我们可以跳过,因为只要后面的步聚正确,一样能解决乱码问题
2.在PHPMYADMIN或mysql-front等系统 创建数据库时会让你选择一种编码,如果这种编码与你的网页不一致,也有可能造成JSP页面乱码.
解决方案:修改数据库编码,如果是数据库编码不正确: 可以在phpmyadmin 执行如下命令: ALTER DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin 。这个命令就是将test数据库的编码设为utf8
3.创建表时会让你选择一种编码,如果这种编码与你的网页编码不一致,也可能造成JSP页面乱码
解决方案:修改表的编码:
ALTER TABLE `category` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin
这个命令就是将一个表category的编码改为utf8
4.创建表时添加字段是可以选择编码的,如果这种编码与你的网页编码不一致,也可能造成JSP页面乱码
解决方案:修改字段的编码:
ALTER TABLE `test` CHANGE `dd` `dd` VARCHAR( 45 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
这个命令就是将test表中 dd的字段编码改为utf8
5.用户提交JSP页面的编码与显示数据的JSP页面编码不一致,就肯定会造成JSP页面乱码.
解决方案:如果是这种情况容易解决,只需检查一下页面,修改源文件的charset即可。如用户输入资料的JSP页面是big5码, 显示用户输入的JSP页面却是gb2312,这种100%会造成JSP页面乱码
6.字符集不正确
解决方案:要注意:
1>.平时你在某些网站看到的文字可能有几种编码, 如你看到一个繁体字,它有可能是big5编码,也有 可能是utf-8编码的,更有可能是gb码的,没错,也就是说有简体编码的繁体字,也有繁体编码的简体字,一定要了解这一点.
2>.如果你是做一个简体编码的网页,编码定为GB2312,如果有香港和台湾地区的访客提交繁体的信息,就可能会造成乱码,解决方法就是(A)将网站编码设为utf-8,这样可以兼容世界上所有字符, (B)如果网站已经运作了好久,已有很多旧数据,不能再更改简体中文的设定,那么建议将页面的编码设为GBK,GBK与GB2312的区别就在于:GBK能比GB2312显示更多的字符,要显示简体码的繁体字,就只能用GBK
7.JSP连接MYSQL数据库语句指定的编码不正确
解决方案:在JSP连接数据库的语句中,带上
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true,
但是千万不要犯和我同样的错误哦。
8.JSP页面没有指定数据提交的编码,就会造成乱码:
解决方案:这种乱码的情况,只需在页面开头加上request.setCharacterEncoding("GBK"); 指定提交的即可。
总而言之,JSP乱码的原因无非就是以上几种,以后再遇到这种问题,先要判断JSP乱码是插入数据库之后乱码,还是JSP页面刚提交过来就乱码了,如果JSP刚接收上一页面的数据显示就乱码了,肯定是字符集不对,可者没有加request.setCharacterEncoding("GBK");
如果是数据库的原因就参考上面的2,3,4种方法
可能是编码问题
这样连接一下数据库看看
jdbc:mysql://localhost:3306/xxxx useUnicode=true&characterEncoding=UTF-8
看看能否有效果
注意:按照以上方法修改以后只能保证你新插入的数据不会乱码,举个例:如果你用户已提交的数据是BIG5,你却想通过以上方法改为可以在GB2312的网页正确显示是不可能的, 这种文字内码的变换只能通过另写程序来解决,请WEB745.com其它相关文章
四.怎么在程序里查看客户端发送给服务器的SQL使用什么编码呢?
在客户端写个程序,执行SQL语句:
public void test() throws SQLException {
ResultSet rs = this.cnn.createStatement().executeQuery("SHOW VARIABLES LIKE 'character_set_%'");
while(rs.next()){
System.out.println(rs.getString(1)+","+rs.getString(2));
}
rs.close();
}
没有配置characterEncoding=utf-8之前,我使用的是DBURL=jdbc:mysql://192.168.0.10:3306/test?useUnicode=true&characterEncoding=utf-8 这样的配置。结果用test()方法查询结果如下:
character_set_client,latin1
character_set_connection,latin1
character_set_database,utf8
character_set_filesystem,binary
character_set_results,
character_set_server,latin1
character_set_system,utf8
character_sets_dir,/usr/local/mysql-standard-5.0.27-linux-i686/share/mysql/charsets/
注意第一行就可以了,可见使用的是latin1。
而latin1本身就无法表示汉字,经过这个编码打包的SQL语句发给Server,Server也用Latin1解析也无法还原。
所以,我总是写乱码到DB。
而配置了配置characterEncoding=utf-8之后,
执行select(),结果:
character_set_client,utf8
character_set_connection,utf8
character_set_database,utf8
character_set_filesystem,binary
character_set_results,
character_set_server,latin1
character_set_system,utf8
character_sets_dir,/usr/local/mysql-standard-5.0.27-linux-i686/share/mysql/charsets/
第一行为utf-8,SQL将用UTF8打包给Server,Server也用Client配置的UTF8解析。