我在一個表中有一個帶有德語“Umlaute ??ü”的 mysql 資料庫,我需要撰寫一個讀取該表的 Go 應用程式,將其編碼為 ISO-8859-1 并將其寫入文本檔案。
到目前為止一切順利,但對 iso-8859-1 的編碼不起作用。所以我現在除錯了兩天以來幾乎所有的東西,現在我被卡住了。
這里有一些細節和資訊:
MySQL mysql 資料庫是 UTF8 的,表本身也是如此。除了character_set_server,其他字符集也應該沒問題,但我認為這與這里無關,據我所知,它應該只是新資料庫的默認值。
當我使用以下 sql 查詢資料庫時,我得到了正確的 UTF8 編碼文本:
select street, hex(street) from test_table where id = '36'
Result: (in real it is called Fr?belstra?e)
Fr??belstra??e, 4672C3B662656C73747261C39F65
所以從十六進制字串來看,它基本上正是我所期望的。行。
Go App 只是相關部分....
db, err := sql.Open("mysql", "...<connection string>...")
res, err := db.Query("select street from from test_table where id = '36'")
for res.Next() {
var pb Phonebook
err := res.Scan(&pb.Street)
fmt.Println(hex.EncodeToString([]byte(pb.Street)))
}
輸出是
4672c383c2b662656c73747261c383c5b865
這就是為什么我對 ISO-8859-1 的編碼不起作用的問題,因為資料庫中的字串不正確。db 直接查詢的十六進制是正確的,并且也可以使用編碼。
但我不明白為什么我從 go 客戶端得到不同的字串。
在原始字串“Fr?belstra?e”中有 2 個字符“?”,即 C3B6 和“?”,即 C39F。使用 db 客戶端查詢的十六進制是可以的,但是來自 go 應用程式的十六進制太長,因為我每個字符多得到 2 個位元組。
當我用正確的十六進制字串輸入我的 latin1 轉換器時,它作業正常,我得到一個 iso-8859-1 字串。但不是從我直接從 go 查詢的另一個。
我這樣做
d := charmap.ISO8859_1.NewEncoder()
out, err := d.String(inp)
也只是一個片段,我實際上用字串呼叫了一個函式,但我從來沒有得到正確的 iso8859-1 結果。所以我用mysql客戶端查詢中的十六進制代碼嘗試了它,轉換回字串,然后賓果游戲iso8859-1結果是正確的。
我還嘗試從 python 查詢并從查詢的字串中獲取相同的奇怪十六進制,所以我完全不知道這里出了什么問題。不能去,因為它在python中是一樣的。但是在資料庫中,我認為它存盤正確,mysql字符集都設定為utf8mb4或utf8,除了我上面提到的那個。
有任何想法嗎?謝謝!
uj5u.com熱心網友回復:
4672c383c2b662656c73747261c383c5b865似乎是“雙重編碼”。在UTF-8 字符的麻煩中查找;我看到的不是我存盤的
但是,由于您是從應用程式而不是表格中獲取十六進制,因此尚無定論。請SELECT HEX(col) FROM ...看看你是否得到了那個字串。通常,應用程式,尤其是瀏覽器,會嘗試“修復”問題,從而使正確診斷變得更加困難。
如果你有“CHARACTER SET utf8mb4雙重編碼”,那么這可能會治愈資料:
UPDATE tbl SET col = CONVERT(BINARY(CONVERT(col USING latin1)) USING utf8mb4);
但是,您也需要修復資料的來源。
uj5u.com熱心網友回復:
經過兩天的徹底迷失,我自己找到了根本原因。奇怪的是,它發生在我在這里發布問題后不久。
我想嘗試不同的 mysql 服務器,因此轉儲了表。然后我在轉儲中看到每個欄位都有自己的字符集定義,在我的例子中是 latin1。
所以這就解釋了為什么這是一個奇怪的結果。我剛剛創建了一個正確的編碼測驗表,它現在按預期作業。
現在我必須考慮如何“修復”這些編碼,也許轉儲/恢復會做到這一點,但那是另一回事了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/419702.html
標籤:
