"知乎原鏈, 作者亦本人" 事情起源於項目另一開發者在中文Windows下構建時遇到的 "部分中文出現亂碼問題" . 當時很不解的是, 為什麼會只有部分出現亂碼. 第一感覺是, 如果編碼轉換不正確, 要麼全亂碼, 要麼全正確. 為何會"部分"出現亂碼. 初步分析 "在此" . 簡單說, 就是在轉碼過 ...
事情起源於項目另一開發者在中文Windows下構建時遇到的部分中文出現亂碼問題.
當時很不解的是, 為什麼會只有部分出現亂碼. 第一感覺是, 如果編碼轉換不正確, 要麼全亂碼, 要麼全正確. 為何會"部分"出現亂碼.
初步分析在此. 簡單說, 就是在轉碼過程中, Java會把某些它不認識的部分直接用某個值代替. 至於為何不預設保留原數據, 是個好的考古研究課題.
示例如下(除了"開始檢", 其他都亂碼了):
編碼 | 原字1 | 原字2 | 原字3 | 原字4 | 原字5 | 原字6 |
---|---|---|---|---|---|---|
原字 | 開 | 始 | 檢 | 查 | … | … |
UTF8表示 | e5 bc 80 | e5 a7 8b | e6 a3 80 | e6 9f a5 | e2 80 a6 | e2 80 a6 |
轉為GBK後 | e5 bc 3f | e5 a7 8b | e6 a3 80 | e6 9f a5 | e2 3f a6 | e2 3f 3f |
轉回UTF8 | �? | 開 | 始 | 檢 | �?� | �?? |
網上很多資源提到字元數是奇數會有問題, 這是沒錯. 但實際上即使偶數也可能會有問題. 上面的轉換過程中, 80
不是合法GBK字元, 就被替換成3f
. 而替換過後再轉回UTF8當然就掛了.
這個問題里的插件就是把輸出字元串指定編碼成了UTF8格式的數據, 但輸出/解碼時又用了系統預設的編碼格式(GBK). 詳見 GBK<->UTF8 互轉問題: Maven checkstyle輸出亂碼 · Issue #26 · program-in-chinese/overview, zh-cn ,,,, cmd gbk encode · Issue #3569 · checkstyle/checkstyle.
個人覺得這種轉碼問題是除了亞洲/非洲之外的開發者很容易忽視的. UTF8的字元除了亞洲(包括中日韓)和非洲語言的字元用三位元組數據表示外, 其他多數語言的字元都是用單位元組或雙位元組. 來源). 這些UTF8中三位元組的字元和GBK之類的雙位元組碼轉碼時會更容易出問題.
在調查過程中, 還發現了其他一些類似疑問, 比如UTF-8編碼,部分中文正常,部分為亂碼的問題?-CSDN論壇.
直覺是也是類似問題, 但想用編碼互轉的方式重現未果, 參考上面的例子試了幾種2次轉碼, 都沒有重現. JDBC連接MySQL拋出異常信息亂碼 - insist的專欄 - CSDN博客提到了CP1252編碼, 又經過幾次嘗試, 才試出了這個過程: "utf-8"->"windows-1252"->"iso-8859-1"->"utf-8".
階段總結一下, 亂碼問題的緣由都是編碼互轉. 全部亂碼, 部分亂碼都可能. 隨著國外代碼庫/軟體的編碼方式更多地使用UTF8, 類似第二個問題的可能會變少, 但類似第一個的UTF8<->GBK互轉的問題也許會存在很長一段時間.