来自MYSQL DB编码的字符串查询在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),但我不确定,只是一个猜测。
我做了一个show table状态,看到我查询的表有Collation of utf8_general_ci
我查询的表没有任何adddtionaly编码定义, 字段name是varchar(512)。
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(512) | YES | | NULL | |
我导入的SQL连接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 |
+----------------------+-------------------+
所以我在数据库控制台上发出了命令:
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 |
+----------------------+-----------------+
不幸的是,这仍未解决问题。
有人能告诉我如何在不清除数据库的情况下纠正这个问题吗?
答案 0 :(得分:1)
首先,我意识到我使用的表格具有UTF-8的编码,但是输入它的源表是latin1,这证实了我对我认为编码的怀疑。
编写代码以将数据从一个复制到另一个的人没有编码转换,因此我觉得到那时数据已经损坏了编码。
我进行了各种实验,包括用
连接到数据库?useUnicode=yes&characterEncoding=UTF-8
我还在SQL控制台上玩了以下内容:
SET character_set_client=latin1;
SET character_set_connection=latin1;
SET character_set_database=latin1;
SET character_set_results=latin1;
以及使用my.cnf和设置的各种变化:
[mysqld]
character-set-server = utf8
character-set-filesystem = utf8
无论如何,这一切都没有帮助。所以最后为了证明它不是一个java问题,但它是一个损坏的数据集,我用UTF8编码创建了我自己的表,将名称存储在那里并让我的程序提取数据。看起来很正确。所以现在需要修复原始表格内容。
我唯一无法解释的是python程序如何不将此标记为问题。这不是我第一次遇到python的宽恕而不是Java的强类型,这在这些情况下是一种祝福和痛苦。
==============================
更新2015/08/19:
当我将源表修复为UTF8并正确存储数据时,Java代码工作正常,但python代码坏了。
要在python中修复它我只添加了
self.cdb = MySQLdb.connect(host=LOCAL_MYSQL_HOST,port=LOCAL_MYSQL_PORT,
user=LOCAL_MYSQL_USER,
passwd=LOCAL_MYSQL_PASS,
db=LOCAL_MYSQL_DB,use_unicode=True,charset="UTF8")
这解决了它。
不幸的是,当我尝试使用Java驱动程序解决此问题时,它无效:
dbStr = String.format("jdbc:mysql://%s:%d/%s?useUnicode=yes&characterEncoding=latin1", esConfig.LOCAL_MYSQL_HOST, esConfig.LOCAL_MYSQL_PORT, esConfig.LOCAL_MYSQL_DB);
我使用的是java 1.7.80,而jdbc包是mysql-connector-java-5.1.36-bin.jar,这是我从Oracle发现的最新内容
答案 1 :(得分:1)
你有 Mojibake 。
SET NAMES latin1
(或set_charset('latin1')
或...)相关联。 (应该是utf8
。)CHARACTER SET latin1
。 (或者它可能是从表/数据库继承的。)(应该是utf8
。)CHARACTER SET utf8
,也可能不是ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...;
ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...;
,但应该是这样。如果您需要修复数据,则需要“两步更改”,例如
JFrame frame = new JFrame("Title");