来自MYSQL DB Query的编码的字符串在Java

时间:2015-08-11 05:01:09

标签: java mysql utf-8 character-encoding

来自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状态,看到我查询的表有Collat​​ion 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 |
+----------------------+-----------------+

不幸的是,这仍未解决问题。

有人能告诉我如何在不清除数据库的情况下纠正这个问题吗?

2 个答案:

答案 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

  • 客户端中的字节在utf8(正常)中正确编码。
  • 您可能默认与SET NAMES latin1(或set_charset('latin1')或...)相关联。 (应该是utf8。)
  • xx表中的列已声明为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");