2014-10-16 87 views
1

情況: latin1數據庫已經轉儲爲latin1,通過iconv轉換爲utf8並恢復爲utf8_unicode_ci。MySQL將latin1轉換爲utf8,cp1252 0x80-0x9F錯誤

看來每個轉換都很好,除了cp1252的0x80-0x9F。我沒有完全理解mysql通過將這些字符翻譯成unicode的含義:mysql

latin1是默認字符集。 MySQL的latin1與Windows cp1252字符集相同。這意味着它與官方的ISO 8859-1或IANA(互聯網號碼分配機構)latin1相同,只不過IANA latin1將0x80和0x9f之間的代碼點視爲「未定義」,而cp1252以及MySQL的latin1分配字符爲那些職位。例如,0x80是歐元符號。對於cp1252中的「undefined」條目,MySQL將0x81轉換爲Unicode 0x0081,0x8d轉換爲0x008d,0x8f轉換爲0x008f,0x90轉換爲0x0090,並將0x9d轉換爲0x009d。

我的表格顯示了例如€0xC280而不是€0x80。所以我想通過

iconv -f latin1 -t utf8 

,而不是我應該

iconv -f cp1252 -t utf-8 

已經轉換我被誤導轉換爲我的測試顯示。因爲第二行工作正確。

所以問題是,如果有可能糾正那些不好的字符或我必須轉儲整個數據庫?

編輯: 是否可以轉儲數據庫壞,並通過

--default-character-set=utf8 
    iconv -c -f utf-8 -t latin1 
    iconv -f latin1 -t utf-8 

再次轉換,然後插入到數據庫? iconv -c會幫助我還是失去信息?

EDIT2: 看來,有可能一個接一個使用更換破損字符:

update history set note = replace(note,unhex('C280'),unhex('E282AC')); 

這將成功地替換爲正確的3byte UTF8錯誤2字節glibberish。 當然,這必須爲每個varchar/text列以及 0x80-0x9F範圍內的每個壞字符完成,這是不方便的。 所以希望有人有一個更好的主意?

回答

0

據我明白iconv命令是基於C的iconv功能: http://www.gnu.org/software/libiconv/documentation/libiconv-1.11/iconv.3.html

的的iconv函數返回該呼叫期間轉換在 非可逆方式中的字符數;計數可逆轉換不是 。如果發生錯誤,它會設置errno並返回(size_t)( - 1)。

因此,您可以嘗試反向轉換,但根據文檔,結果取決於第一次轉換的返回碼。當然你可以嘗試二進制替換無效字符。

+0

不好,我沒有得到任何數字,因爲我沒有打印返回代碼:( 你的二進制方法將如何看起來像? – gantners 2014-10-16 21:24:15

+1

這可能會有所幫助http://stackoverflow.com/questions/7760717/hex-string-replacement-using-sed – Matzz 2014-10-17 07:52:09