mysql處理Latin 中文繁體字亂碼解決方案

 

問題描述:

1. 對於一些中文繁體字符select出來出現亂碼,出問題的繁體字如:燈、龍等

 

環境描述:

數據庫編碼:

 

+--------------------------+----------------------------------------+

| Variable_name            | Value                                  |

+--------------------------+----------------------------------------+

| auto_increment_offset    | 1                                      |

| character_set_client     | latin1                                 |

| character_set_connection | latin1                                 |

| character_set_database   | latin1                                 |

| character_set_filesystem | binary                                 |

| character_set_results    | latin1                                 |

| character_set_server     | latin1                                 |

| character_set_system     | utf8                                   |

| character_sets_dir       | D:/Program Files/mysql/share/charsets/ |

+--------------------------+----------------------------------------+

數據庫表編碼:也同意使用latin1編碼方式

由於數據庫由DBA負責,並且庫結構爲了保持一致(我們使用備份庫),從而不能修改數據庫編碼

 

 

 

問題排查:

1.mysql 的jdbc驅動源代碼拷貝下來DEBUG,最終發現了問題根源在驅動中CharSetMapping.class該類中的getJavaEncodingForMysqlEncoding(String mysqlEncoding,Connection conn)方法,該方法源代碼如下:

public final static String getJavaEncodingForMysqlEncoding(String mysqlEncoding, Connection conn) throws SQLException { if (conn != null && conn.versionMeetsMinimum(4, 1, 0) && "latin1".equalsIgnoreCase(mysqlEncoding)) { return "Cp1252"; } return (String) MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlEncoding); } 

這裏Latin1編碼就是iso-8859-1編碼。問題就出在這裏,mysql驅動對Latin1編碼做了特殊處理,轉爲cp1252,但cp1252依然屬於Latin1系編碼,故顯示中文依然會存在亂碼,故需要在GBKstring中轉化cp1252.

這麼做了以後,發現我看到的中文都不再亂碼OK,包括一些繁體字和火星文,大功告成了。

過了一天,我們測試給我反饋結果,說一些繁體字依然存在亂碼,比如“燈、龍”等,在頁面上顯示“?”,究竟哪兒出了問題?繼續DEBUG,

發現普通漢字從Latin1轉碼爲cp1252後的byte array中的數據中,用兩個字節表示一個漢字時,能夠在GBK編碼映射表中找到byte array對應的2字節數據,而“燈、龍”兩個繁體字轉cp1252後,其對應的byte array中的2字節數據無法再GBK編碼中找到(既GBK中無法找到該2字節數據對應的漢子),從而出現“?”。

故問題應該就出現在這裏,既從latin1->cp1252->gbk這樣一個過程會出現以下編碼數據丟失。從而解決方案也是很明顯的:

既:去掉中間轉cp1252的步驟,直接將Latin1 轉gbk,同時gbkString中不處理,將上面代碼修改爲:

public final static String getJavaEncodingForMysqlEncoding(String mysqlEncoding, Connection conn) throws SQLException { if (conn != null && conn.versionMeetsMinimum(4, 1, 0) && "latin1".equalsIgnoreCase(mysqlEncoding)) { return "gbk"; } return (String) MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlEncoding); } 

再一測試,問題解決!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章