2017-04-10 46 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

「ç而不是ç」 - 這個問題解決了嗎? –