来自 MYSQL 数据库查询的编码字符串在 Java 中被破坏
String with encoding from MYSQL DB Query comes through as mangled in Java
编码来自 MYSQL 数据库查询的字符串在 Java
中被破坏
使用 Java,我正在连接到 MYSQL 数据库,我在其中查询 table 以收集
它的一个字段。
该字段有 UTF8 编码的文本,即:
Córas Éireann
上面的文字是我登录MYSQL控制台时看到的,看看
table 中的那一行。 mysql 部署的版本是:
mysql Ver 14.14 Distrib 5.1.52,用于未知-linux-gnu (x86_64) 使用 readline 5.1
如果我使用python程序连接到相同的数据库并查询相同的
table 并得到同一行,文本看起来是正确的,即它以 Córas Éireann
的形式出现
然而,当我通过Java查询时,文本显示为:
Córas Éireann
我怀疑是西方的 (ISO latin1),但我不确定,只是猜测。
我显示了 table 状态,看到我正在查询的 table 有 Collation
utf8_general_ci
我查询的table没有任何额外的编码定义,
字段名称是一个 varchar(512).
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(512) | YES | | NULL | |
我导入的SQLconnect 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,我什么都不做decoding/encoding,查询和连接都是
基本的,我得到了正确的字符串。我是否缺少需要的步骤
要在 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()
谢谢...阿姆罗
--------更新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
然后 table 进化为:
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 |
+----------------------+-----------------+
不幸的是,这仍然没有解决问题。
谁能告诉我如何在不清除数据库的情况下更正此问题?
首先我意识到我使用的 table 有 UTF-8 编码,但是输入它的源 table 是 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
无论如何,none 这有帮助。所以最后为了证明这不是 java 问题而是损坏的数据集,我用 UTF8 编码创建了自己的 table,将名称存储在那里并让我的程序提取数据。它看起来是正确的。所以现在是修复原始 table 内容的问题。
我唯一无法解释的是 python 程序为何没有将此标记为问题。这不是我第一次遇到 python 对 Java 的强类型的宽恕,这在这些情况下是一种祝福和痛苦。
================================
2015/08/19 更新:
当我将源 table 固定为 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
找到的最新信息
您有 Mojibake。
- 您在客户端中的字节已正确编码为 utf8(良好)。
- 您连接的是
SET NAMES latin1
(或 set_charset('latin1')
或...),可能是默认连接。 (应该是utf8
。)
- xx table 中的列已声明为
CHARACTER SET latin1
。 (或者可能是继承自 table/database。)(应该是 utf8
。)
- table 中的列可能是也可能不是
CHARACTER SET utf8
,但应该是。
如果您需要修复数据,则需要“两步更改”,例如
ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...;
ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...;
编码来自 MYSQL 数据库查询的字符串在 Java
中被破坏使用 Java,我正在连接到 MYSQL 数据库,我在其中查询 table 以收集 它的一个字段。
该字段有 UTF8 编码的文本,即:
Córas Éireann
上面的文字是我登录MYSQL控制台时看到的,看看 table 中的那一行。 mysql 部署的版本是: mysql Ver 14.14 Distrib 5.1.52,用于未知-linux-gnu (x86_64) 使用 readline 5.1
如果我使用python程序连接到相同的数据库并查询相同的 table 并得到同一行,文本看起来是正确的,即它以 Córas Éireann
的形式出现然而,当我通过Java查询时,文本显示为:
Córas Éireann
我怀疑是西方的 (ISO latin1),但我不确定,只是猜测。
我显示了 table 状态,看到我正在查询的 table 有 Collation utf8_general_ci
我查询的table没有任何额外的编码定义, 字段名称是一个 varchar(512).
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(512) | YES | | NULL | |
我导入的SQLconnect 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,我什么都不做decoding/encoding,查询和连接都是 基本的,我得到了正确的字符串。我是否缺少需要的步骤 要在 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()
谢谢...阿姆罗
--------更新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
然后 table 进化为:
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 |
+----------------------+-----------------+
不幸的是,这仍然没有解决问题。
谁能告诉我如何在不清除数据库的情况下更正此问题?
首先我意识到我使用的 table 有 UTF-8 编码,但是输入它的源 table 是 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
无论如何,none 这有帮助。所以最后为了证明这不是 java 问题而是损坏的数据集,我用 UTF8 编码创建了自己的 table,将名称存储在那里并让我的程序提取数据。它看起来是正确的。所以现在是修复原始 table 内容的问题。
我唯一无法解释的是 python 程序为何没有将此标记为问题。这不是我第一次遇到 python 对 Java 的强类型的宽恕,这在这些情况下是一种祝福和痛苦。
================================
2015/08/19 更新:
当我将源 table 固定为 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
找到的最新信息您有 Mojibake。
- 您在客户端中的字节已正确编码为 utf8(良好)。
- 您连接的是
SET NAMES latin1
(或set_charset('latin1')
或...),可能是默认连接。 (应该是utf8
。) - xx table 中的列已声明为
CHARACTER SET latin1
。 (或者可能是继承自 table/database。)(应该是utf8
。) - table 中的列可能是也可能不是
CHARACTER SET utf8
,但应该是。
如果您需要修复数据,则需要“两步更改”,例如
ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...;
ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...;