DEV Community

ScottPony
ScottPony

Posted on

為什麼資料庫顯示亂碼?深入探討 Latin1 與 Windows-1252 的編碼衝突

在日常開發中,處理文字編碼問題是不可避免的挑戰。特別是在多語言環境下,編碼不一致可能導致程式無法正確解析資料,進而影響系統的穩定性。本文將分享一個實際案例,深入探討為何資料庫會顯示亂碼,以及如何解決 Latin1 與 Windows-1252 編碼衝突的問題。

問題背景

在一個專案中,我們從客戶端的資料庫查詢工具中,發現某筆記錄的欄位內容顯示為亂碼。這個欄位的資料類型為 OID(帶有 0x 前綴的十六進位字串),同時也是另一張資料表的鍵值。

當我們在程式中嘗試讀取這筆資料並解析為位元組陣列時,卻拋出了無法解析的錯誤。經過在 IDE 中的除錯,我們確認程式讀取到的確實是亂碼,導致自訂的 toByteArray() 方法無法正常運作。

至此,我們判斷這是由於編碼問題導致程式無法繼續執行。

Garbled text in the database

問題調查過程

為了找出問題的根源,我們展開了以下調查:

  1. 線上轉碼測試:使用線上轉碼工具(如 Text轉Hex),將亂碼貼上並嘗試不同的編碼格式,觀察轉換後的十六進位字串是否與資料庫查詢工具所得到的結果一致。
  2. 確認資料庫編碼:得知資料庫中的欄位編碼設定為 "Latin1"(即 ISO-8859-1)。在轉碼工具中選擇 "ISO-8859-1" 編碼,成功將亂碼轉換為與資料庫一致的十六進位字串。
  3. 程式內部測試:在程式中使用 .NET 提供的 Encoding.Latin1.GetBytes("myString") 方法,嘗試將亂碼轉換為位元組陣列。雖然這次沒有拋出例外,但轉換後的位元組陣列與預期結果不符。
  4. 分析差異:深入比較發現,轉換結果中只有第一個字元不同。該字元為歐元符號 (€),而在 ISO-8859-1 編碼中,編碼範圍 0x80 至 0x9F 並未定義。

找出問題根源

了解到問題可能出在歐元符號的編碼上,我們進一步研究:

  • ISO-8859-15 編碼:這是 ISO-8859-1 的擴充版本,定義了歐元符號。然而,歐元符號在 ISO-8859-15 中對應的十六進位值為 0xA4,與我們的資料並不匹配。

  • Windows-1252 編碼:查閱相關資料得知,Windows-1252 編碼(又稱 CP1252)在 0x80 至 0x9F 範圍內定義了額外的可見字符,包括歐元符號。其中,歐元符號對應的十六進位值正是 0x80。

這意味著,雖然資料庫宣稱使用 Latin1 編碼,但實際上存儲的資料包含了 Windows-1252 編碼的字符。

解決方案

基於以上調查,我們決定在程式中採用 Windows-1252 編碼進行轉換。具體實現如下:

byte[] byteArray = Encoding.GetEncoding("CP1252").GetBytes("myString");
Enter fullscreen mode Exit fullscreen mode

使用 Encoding.GetEncoding("CP1252") 方法,我們成功將亂碼正確轉換為位元組陣列,並與資料庫中的十六進位字串一致。問題終於得到了解決。

總結

這次的經驗提醒我們,在處理文字編碼時,不能僅依賴於表面設定的編碼格式。實際存儲的資料可能包含超出宣告範圍的字符,特別是在歷史悠久或多元化的系統中。

為避免類似問題,建議:

  • 確認實際編碼:使用工具或程式檢查資料實際使用的編碼,而非僅依賴於設定。

  • 統一編碼標準:在系統中盡可能統一使用 UTF-8 或其他廣泛支持的編碼,減少編碼衝突的可能性。

  • 加強錯誤處理:在程式中加入編碼錯誤的處理機制,便於快速定位問題。

透過深入的調查和分析,我們不僅解決了當前的問題,還為未來處理類似情況積累了寶貴的經驗。

Top comments (0)