【发布时间】:2015-08-11 05:01:09
【问题描述】:
带有 MYSQL DB Query 编码的字符串在 Java 中被破坏
我使用 Java 连接到一个 MYSQL 数据库,在该数据库中查询一个表以进行收集 一个字段。
该字段有UTF8编码的文本,即:
Córas Éireann
上面的文字是我登录MYSQL控制台看的时候看到的 表中的那一行。部署的mysql版本为: mysql Ver 14.14 Distrib 5.1.52,用于使用 readline 5.1 的 unknown-linux-gnu (x86_64)
如果我使用 python 程序连接到同一个数据库并查询相同 表并获得相同的行,文本看起来正确,即它来自 Córas Éireann
但是,当我通过 Java 查询时,文本显示为:
Córas Éireann
我怀疑是西方(ISO latin1),但我不确定,只是猜测。
我做了一个显示表状态,发现我正在查询的表有排序规则 utf8_general_ci
我查询的表没有任何额外的编码定义, 字段名称是 varchar(512)。
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(512) | YES | | NULL | |
我导入的SQL connect JAR是mysql-connector-java-5.1.36,我也试过v 5.1.34 和 5.0.8 但没有区别。
这就是我连接数据库的方式:
String dbStr =
String.format("jdbc:mysql://%s:%d/%s?useUnicode=yes&characterEncoding=UTF-8", LOCAL_MYSQL_HOST,
LOCAL_MYSQL_PORT, LOCAL_MYSQL_DB);
try {
cdb = DriverManager.getConnection(dbStr, LOCAL_MYSQL_USER, LOCAL_MYSQL_PASS);
Statement dbStatement = cdb.createStatement();
String query = String.format("SELECT name FROM customer WHERE id=%d",customerId);
ResultSet row = dbStatement.executeQuery(query);
if (row.first()) {
System.out.println("name is " + row.getString("name");
}
} catch (SQLException exc) {
exc.printStackTrace();
}
请注意,我的原始实现不包含
?useUnicode=yes&characterEncoding=UTF-8
但添加它并没有使它变得更好 或更糟。我添加了它,因为我认为这可能是 罪魁祸首。我还尝试了 latin1 而不是 utf-8 来看看这是否 差异但没有运气,结果完全相同,即它出来为 Córas Éireann.
我什至尝试过这样的事情:
byte[] rowBytes = row.getBytes("name");
String utfdecocedStr = new String(rowBytes, "UTF-8");
System.out.println(utfdecocedStr);
但输出仍为 Córas Éireann
在python中,我不做任何解码/编码,查询和连接都是 基本的,我得到了正确的字符串。我是否缺少需要的步骤 在 DB 或 Java 端完成以使其正常工作?在 my.conf 中,我没有 有任何设置来设置任何编码配置。
Python 方法:
import MySQLdb
cdb = MySQLdb.connect(host=LOCAL_MYSQL_HOST,port=LOCAL_MYSQL_PORT,
user=LOCAL_MYSQL_USER,
passwd=LOCAL_MYSQL_PASS,db=LOCAL_MYSQL_DB)
ccursor = self.cdb.cursor()
query = """SELECT name FROM customer WHERE id='%d' """%(customer_id)
row = ccursor.execute(query)
if row:
customername = ccursor.fetchone()
谢谢你...Amro
---------更新20150811---------------
我在数据库上运行了以下命令,发现以下配置可能解释了我所看到的行为:
show variables like 'character%';
+--------------------------+---------------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/percona-xtradb-cluster/charsets/ |
+--------------------------+---------------------------------------------+
8 rows in set (0.00 sec)
mysql> show variables like 'collation%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
通过将以下内容添加到 my.cnf:
character-set-server = utf8
character-set-filesystem = utf8
然后表格演变为:
mysql> 显示 'character%' 等变量;
+--------------------------+---------------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | utf8 |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/percona-xtradb-cluster/charsets/ |
+--------------------------+---------------------------------------------+
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | utf8_general_ci |
+----------------------+-------------------+
所以我在 DB 控制台上发出了命令:
ALTER DATABASE <dbname> CHARACTER SET utf8;
显示像'character%'这样的变量;
+--------------------------+---------------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | utf8 |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/percona-xtradb-cluster/charsets/ |
+--------------------------+---------------------------------------------+
8 rows in set (0.00 sec)
mysql> show variables like 'collation%';
+----------------------+-----------------+
| Variable_name | Value |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8_general_ci |
| collation_server | utf8_general_ci |
+----------------------+-----------------+
很遗憾,这仍然没有解决问题。
有人可以告诉我如何在不清除数据库的情况下纠正这个问题吗?
【问题讨论】:
-
首先,您需要确保在存储字段时,您使用的是相同的 UTF-8 格式。数据库本身的数据是否损坏?您可以尝试在
new String(rowBytes, "ISO-8859-1")中使用ISO-8859-1。但是你在哪里得到这个作为输出Córas Éireann在你的服务器控制台或你的 IDE 控制台上? -
您如何查看 java 中的输出?如果这是通过 Eclipse,您是否可以尝试在 Run -> Run Configurations -> Common 更改 Eclipse 控制台的编码
-
@UtKarash,数据库中的数据很好,正如我指出的,如果我通过连接到 mysql 控制台或 python 查看数据,编码会正确显示。所以数据库数据没有损坏。我使用 IntelliJ 作为我的 IDE,并将其设置为 UTF-8。输出 Córas Éireann 被转储到我的服务器控制台(终端窗口)上,我从中运行我的 java 程序和我的 python 程序。
-
你似乎在做所有正确的事情。可以检查一下:stackoverflow.com/questions/5405236/… 在上面的链接中,
my.cnf用于 linux,my.ini用于 Windows。在这些文件中添加字符集default-character-set=utf8有时可以解决问题。 -
@UTKarash,谢谢,我会试一试,让你知道。我必须看看是否需要重新启动数据库以强制重新读取 my.conf。数据库部署在 linux 机器上。
标签: java mysql utf-8 character-encoding