写在前面:如果大家的MySQL中使用的是GBK或UTF-8,但是在Windows下的命令行中查看中文数据的时候是乱码,则请先执行以下语句,在进行增删改查:
mysql> SET NAMES GBK;
乱码原因:中文Windows的CMD只支持GBK编码,但是MySQL中是UTF-8编码,不匹配。
此外,如果MySQL在安装的时候选择多语言支持,那么你稍后创建Schema,Table时,无论指定的编码是GBK,还是UTF-8,貌似都一样,它内部都是使用UTF-8或UNICODE存储的 --- 推测啦,未调查。
/* mysql JDBC 乱码原因探究
参考: mysql文档第10章: Character Set Support
写在前面以方便那些没有耐心看完全文的朋友:
解决方法:
无论在mysql的配置是什么字符集, 在创建表(或创建数据库)的时候都明确的指定字符集
如: create table test (....) DEFAULT CHARACTER SET utf8;
在使用 JDBC 的时候都明确指定字符集参数:
如: jdbc:mysql://localhost/test?useunicode=true&characterEncoding=utf8
mysql 有4个字符集设定级别:
服务器级别: 通过编译时指定或在配置文件中通过default-character-set(有两处)指定
数据库级别:
CREATE DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
ALTER DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
表级别:
CREATE TABLE tbl_name (column_list)
[DEFAULT CHARACTER SET charset_name [COLLATE collation_name]]
ALTER TABLE tbl_name
[DEFAULT CHARACTER SET charset_name] [COLLATE collation_name]
列级别:
col_name {CHAR | VARCHAR | TEXT} (col_length)
[CHARACTER SET charset_name [COLLATE collation_name]]
补充说明:
1> 对于上述sql格式中的COLLATE是只得是排序的方法(比如是否大小写敏感排序),
这里只讨论字符集的设定.
2> 可以用show character set;来查看MySql中可用的字符集
当然, 以上4个级别的字符集设定从上往下是适用面越来越窄, 但优先级越来越高.
以下是对比说明表, 假设直接用JDBC插入含有汉字的记录.
服务器字符集 列字符集 JDBC URL参数 现象 汉字输入解决方法
latin1 latin1 无 乱码 string.getBytes()
utf8 无 乱码 无法恢复
gbk 无 乱码 无法恢复
latin1 有 运行异常 string.getBytes()
utf8 有 正常
gbk 有 正常
utf8 latin1 无/有 运行异常 string.getBytes()
utf8 无/有 正常
gbk 无/有 正常
说明:
JDBC URL参数是指
?useunicode=true&characterEncoding=gbk 或
?useunicode=true&characterEncoding=utf8
运行异常是指
SQLException: Data too long for column
string.getBytes()是指:
插入数据库是用 new String(name.getBytes(oneCharSet),iso)
而读取数据库时用 new String(rs.getString("color").getBytes(iso), oneCharSet)
注意:
1> 若列字符集正常且又用了 String.getBytes(), 则会运行异常!
2> 命令行窗口用的是OS默认字符集GBK, 故对于列字符集为urf8的显示会是乱码,
对列字符集为gbk的也是乱码, 则不知原因!
*/
import java.io.*;
import java.sql.*;
import java.lang.*;
public class T{
static String user="root";
static String passwd="123456";
static String gbk = "gbk";
static String iso = "ISO-8859-1";
static String utf = "utf-8";
static String url="jdbc:mysql://localhost/test";//?useunicode=true&characterEncoding=utf8
static String driver = "org.gjt.mm.mysql.Driver";
public static void main(String[] args){
Connection conn = null;
try {
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url, user, passwd);
String name = "张亮亮";
String addr = "哈工大(威海)";
String *** = "男";
String color = "蓝";
Statement stmt = conn.createStatement();
String dropSql = "drop table if exists std ";
String createSql = "create table std ( "
+ " name varchar(32) CHARACTER SET latin1,"
+ " *** varchar(32) CHARACTER SET gbk,"
+ " addr varchar(32) CHARACTER SET utf8,"
+ " color varchar(32) "
+ ");";
String insertSql = "insert into std values('张亮亮"//+new String(name.getBytes(),iso)
+ "','男"//+new String(***.getBytes(),iso)
+ "','哈工大(威海)"//+new String(addr.getBytes(), iso)
+ "','蓝"//+new String(color.getBytes(),iso)
+ "')";
String selectSql = "select * from std";
stmt.executeUpdate( dropSql ); //drop table
stmt.executeUpdate( createSql ); //create table
stmt.executeUpdate( insertSql ); //insert //label_1:
ResultSet rs = stmt.executeQuery(selectSql);
while(rs.next()){
System.out.println(rs.getString("name")); //label_2: +", "+new String(rs.getString("name").getBytes(iso))
System.out.println(rs.getString("***")); //label_3: +", "+new String(rs.getString("***").getBytes(iso))
System.out.println(rs.getString("addr")); //label_4: +", "+new String(rs.getString("addr").getBytes(iso))
System.out.println(rs.getString("color")); //label_5: +", "+new String(rs.getString("color").getBytes(iso))
}
} catch (Exception e){
e.printStackTrace();
}
}
};
/* 详细测试
OS: windows 2003
系统字符集: GBK
mysql 版本: 5.0
1> my.ini 中 default-character-set=utf8
JDBC URL : jdbc:mysql://localhost/test 或者
jdbc:mysql://localhost/test?useunicode=true&characterEncoding=utf8 或者
jdbc:mysql://localhost/test?useunicode=true&characterEncoding=gbk
insertSql: insert into std values('张亮亮','男','哈工大(威海)','蓝')"
lable_1: 运行异常: Data too long for column 'name' at row 1
原因: latin1无法存储汉字, 用 'zhangliangliang' 代替 '张亮亮',
除了修改列的存储字符集尚无解决方案
lable_2: zhangliangliang
lable_3: 男
label_4: 哈工大(威海)
label_5: 蓝
Mysql 命令行结果:
mysql> select * from std;
+-----------------+------+-------------------+-------+
| name | *** | addr | color |
+-----------------+------+-------------------+-------+
| zhangliangliang | 鐢? | 鍝堝伐澶?濞佹捣) | 钃? |
+-----------------+------+-------------------+-------+
1 row in set (0.00 sec)
2> my.ini 中 default-character-set=latin1
JDBC URL : jdbc:mysql://localhost/test?useunicode=true&characterEncoding=utf8 或者
jdbc:mysql://localhost/test?useunicode=true&characterEncoding=gbk
insertSql: insert into std values('张亮亮','男','哈工大(威海)','蓝')"
lable_1: 运行异常: Data too long for column 'name' at row 1
Data too long for column 'color' at row 1
解决方法见最后: 目前先用拼音 zhangliangliang 代替.
lable_2: zhangliangliang
lable_3: 男
label_4: 哈工大(威海)
label_5: 同lable_1, 用blue代替继续测试.
mysql> select * from std;
+-----------------+------+---------+-------+
| name | *** | addr | color |
+-----------------+------+---------+-------+
| zhangliangliang | ? | ???(??) | blue |
+-----------------+------+---------+-------+
1 row in set (0.03 sec)
JDBC URL : jdbc:mysql://localhost/test
insertSql: insert into std values('张亮亮','男','哈工大(威海)','蓝')"
lable_1: 运行无异常
lable_2: ???
lable_3: ?
label_4: ???(??)
label_5: ?
mysql> select * from std;
+------+------+---------+-------+
| name | *** | addr | color |
+------+------+---------+-------+
| ??? | ? | ???(??) | ? |
+------+------+---------+-------+
1 row in set (0.00 sec)
对于 列字符集为utf8(如addr列), latin1(明确设定(如name列)或默认(如color列))有如下解决方法
(其他UNICODE格式未测试, 用GBK也会出现类似运行时异常):
写入时用:new String(addr.getBytes(), iso)
读取时用:new String(rs.getString("addr").getBytes(iso))
并且在命令行窗口也可以正确显示!(毕竟命令行下只用系统字符集)
*/
function winOnLoad_startColor(){
/*由于彩色显示需要给定的CSS文件支持, 而link标签在UCBLOG的源代码编辑时会被
自动删除,所以只能通过Javascript载入css文件*/
var linkElement = document.createElement('link');
linkElement.setAttribute("type", "text/css");
linkElement.setAttribute("rel", "stylesheet");
linkElement.setAttribute("href", "");
document.body.appendChild(linkElement);
dp.SyntaxHighlighter.HighlightAll('code');
}
/*由于此时body还没有完全载入, 所以用onload事件触发来正确完成着色*/
window.attachEvent("onload", winOnLoad_startColor);
阅读(2700) | 评论(4) | 转发(0) |