2017-04-10 57 views
1

日龄问题,从MySql数据库返回查询时,我得到的字符如ç而不是ç。如何解决MySql的JSON和Java的编码问题?

我使用的是一个非常简单的类来尝试钉住问题了下来:

package com.dataTest; 

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 

public class EncodingTest { 

    public static void main(String[] args) throws Exception { 
     Class.forName("com.mysql.jdbc.Driver"); 

     Connection connection = DriverManager 
       .getConnection("jdbc:mysql://internalip:3306/databasename?" + 
           "user=user" + 
           "&password=password" + 
           "&characterEncoding=utf-8" + 
           "&useUnicode=yes"); 

     PreparedStatement stmt = 
       connection.prepareStatement("SELECT * FROM `databasename`.teste_json;"); 
     ResultSet rs = stmt.executeQuery(); 

     while (rs.next()) { 
      System.out.println(rs.getString("info")); 
     } 

     rs.close(); 
     stmt.close(); 
     connection.close(); 
    } 
} 

的信息加入到通过其他类的数据库,但我把它使用手动工作台改变,问题依然存在。

数据库归类为utf8_general_ci,表编码为utf8。

我真的不知道该怎么做。

编辑:

我复制JSON字符串为varchar(1500)字段,并将其完全打印。我忘了提及,查询(info)中提到的字段是JSON字段。

编辑2:它不是mojibake?

问题被关闭基于里克詹姆斯答案声称这是Mojibake。

Acording的问题Trouble with utf8 characters; what I see is not what I stored以下观察:

  • 该字节被存储需要是UTF-8编码的。解决这个问题。

我认为他们存储正确。我做了一个简单的JSON的HEX,长度和CHAR_LENGTH这样的:

'[{\"é\": \"\"}]', '5B7B22C3A9223A2022227D5D', '12', '11' 
  • 连接插入和选择文本需要指定UTF8或utf8mb4时。解决这个问题。

的连接字符串指定的字符集:

&useUnicode=yes&characterEncoding=UTF-8 
  • 列需要声明CHARACTER SET UTF8(或utf8mb4)。解决这个问题。

那么,数据库已字符集/核对= UTF8/utf8_general_ci 该表具有核对utf8_unicode_ci 的JSON柱(这是有问题的一个)没有归类。

有多奇怪。

手动状态

MySQL的处理使用utf8mb4字符集和utf8mb4_bin核对在JSON上下文中使用字符串。其他字符集中的字符串将根据需要转换为utf8mb4。 (对于ascii或utf8字符集中的字符串,不需要转换,因为ascii和utf8是utf8mb4的子集。)

https://dev.mysql.com/doc/refman/5.7/en/json.html

这是否意味着实际整理已经是正确的?

据我所知,插入服务器的信息是正确的(见HEX信息),所以问题是选择?但连接字符串似乎在所有形式中都是正确的。

编辑:不是一个复制。

在这种情况下的问题与其他问题中的问题不同,请参阅我自己对此问题的回答以及所提及的错误报告。

+1

根据这些https://dev.mysql.com/doc/refman/5.7/en/json,您可能会遇到一些问题。html#json转换类型和https://bugs.mysql.com/bug.php?id=81677 – pvg

+0

表的字符集/排序规则是每列的_default_。所以,如果专栏是沉默的,看看这张表。 –

+0

表格的整理是utf8_general_ci,如问题所述。 –

回答

2

TLDR:使用以下utf8mb4,utf16或utf32之一进行转换。

正如用户pvg所评论的,MySql似乎将它们的JSON格式存储在utf8字符类型(utf8mb4,utf8,ascii)中,至少这是他们的文档说的。根据此错误报告(https://bugs.mysql.com/bug.php?id=81677),JSON存储在utf8mb4中,但当前JDBC驱动程序不支持编码(如2017年4月,这是工件mysql-connector-java,版本6.0.6)。

有趣的是,MySQL已经可以使用这样CONVERT(info USING utf8)

更改我的查询到SELECT field1, field2, CONVERT(info USING utf8) as info FROM databasename.teste_json;完全固定我的问题上CONVERT()功能。

以下是MySql中不同编码类型的一些结果。

为了检查会发生什么,我更改了更复杂的字段名称。我使用的字符串是ãõêçé日本语のキーボード

在Java程序中,我在连接字符串中删除了所有编码的引用,这些都是使用MySQL文档中发现了几个编码(https://dev.mysql.com/doc/refman/5.5/en/charset-charsets.html)使用CONVERT结果:

big5  {"name": "??????日本語のキ?ボ?ド"} 
dec8  {"name": "?ãõêçé?????????"} 
cp850 {"name": "?ãõêçé?????????"} 
hp8  {"name": "?âêÁµÅ?????????"} 
koi8r {"name": "???????????????"} 
latin1 {"name": "?ãõêçé?????????"} 
latin2 {"name": "????çé?????????"} 
swe7  {"name": "?????`?????????"} 
ascii {"name": "???????????????"} 
ujis  {"name": "?ãõêçé日本語のキーボード"} 
sjis  {"name": "??????日本語のキーボード"} 
hebrew {"name": "???????????????"} 
tis620 {"name": "???????????????"} 
euckr {"name": "??????日本語のキ?ボ?ド"} 
koi8u {"name": "???????????????"} 
gb2312 {"name": "???ê?é日本?のキ?ボ?ド"} 
greek {"name": "???????????????"} 
cp1250 {"name": "????çé?????????"} 
gbk  {"name": "???ê?é日本語のキーボード"} 
latin5 {"name": "?ãõêçé?????????"} 
armscii8 {"name": "???????????????"} 
utf8  {"name": "?ãõêçé日本語のキーボード"} 
ucs2  {"name": "?ãõêçé日本語のキーボード"} 
cp866 {"name": "???????????????"} 
keybcs2 {"name": "?????é?????????"} 
macce {"name": "??õ??é?????????"} 
macroman {"name": "?ãõêçé?????????"} 
cp852 {"name": "????çé?????????"} 
latin7 {"name": "??õ??é?????????"} 
utf8mb4 {"name": "ãõêçé日本語のキーボード"} 
cp1251 {"name": "???????????????"} 
utf16 {"name": "ãõêçé日本語のキーボード"} 
cp1256 {"name": "???êçé?????????"} 
cp1257 {"name": "??õ??é?????????"} 
utf32 {"name": "ãõêçé日本語のキーボード"} 
binary {"name": "ðãõêçéæ¥æ¬èªã®ã­ã¼ãã¼ã"} 
geostd8 {"name": "???????????????"} 
cp932 {"name": "??????日本語のキーボード"} 
eucjpms {"name": "?ãõêçé日本語のキーボード"} 

请注意,唯一能够正确显示所有字符(包括笑脸)的编码是utf8mb4,utf16,utf32。

编辑:从另一篇文章中的所有讨论,它似乎是JDBC驱动程序中的某种错误,至少一切指向它,目前可能的解决方法是强制CONVERT使用utf8mb4。我强烈如果你想了解更多关于编码问题,推荐阅读通过瑞克詹姆斯在这个问题上的材料。

+0

我很好奇使用JSON类型的优点是什么。看起来像你保证每个JSON文档执行_two_转换到达你的Java客户端。你从JSON得到VARCHAR不给你什么? – pvg

+0

在这种情况下,唯一的好处是在数据库级别有一个JSON验证。在未来的情况下,您可以访问一些JSON函数https://dev.mysql.com/doc/refman/5.7/en/json-functions.html。我认为我应该在使用JSON之前加权我的选项,但这是一个非常有趣的实验,我正在学习很多。 –

+0

我的意思是'出于好奇',而不是一些无知的批评:)这就是说,我认为你应该给@RickJames答案仔细阅读,因为我认为它解决了根本问题 - mysql的utf-8的实现是错误的,打破了,没有人应该使用它。他们的'修复'是组成一个新的编码名称'utf8mb4',这意味着'实际的utf-8通过mysql unfuckedup'。我不确定你必须给jdbc驱动和/或表格设置什么神奇的咒语,但它似乎应该可以在没有'CONVERT'的情况下使这个工作成为可能。 – pvg

1

这就是“Mojibake”。问题和解决方案在

讨论

Trouble with utf8 characters; what I see is not what I stored

的Java:注意其拼写UTF-8,不utf8,也不utf8mb4

添加?useUnicode=yes&characterEncoding=UTF-8到JDBC URL

<%@ page language="java" pageEncoding="UTF-8"%> 
<%@ page contentType="text/html;charset=UTF-8" %> 

compileJava.options.encoding = 'UTF-8' 
<form method="post" action="/your/url/" accept-charset="UTF-8"> 
+0

这似乎更像是问题是你现有的答案,而不是一个新的答案愚人。 – pvg

+0

真的不认为它是Mojibake,看到更新的答案。 –

+0

“ç而不是ç” - 这个问题解决了吗? –