Unicode字元的相容性問題--長得一樣的漢字怎麼會有多個編碼?
昨天半夜幫同學排查問題,明明是一樣的漢字,但是字串比較結果卻是False
檢查了半天,發現是utf-8的編碼不同,對方的Mac電腦的Pycharm把這兩個編碼不同的漢字顯示的完全一樣
玉 玉
你的電腦上看得出來這兩個字的區別麼?
但是在我的電腦(Windows10+VisualStudioCode)上顯示的就很明顯
問題產生的原因
(轉自https://www.qqxiuzi.cn/wz/zixun/1717.htm):
---------------------------------------------------------------------------------------------------------------------------------------
Unicode 之初收錄漢字遵循兩個基本原則:表意文字認同原則和字源分離原則。
所謂表意文字認同原則,即“只對字,不對形”編碼,將同一字的不同字形(即異體字,不適用繁簡體)合併。例如“房”字的第一筆,在中日韓的寫法都不同,但它本身是同一個字,只給一個編碼,而寫法的不同交由字型進行區分。
字源分離原則,是指一個字源中同時收錄了同一個字的不同字形,則給予兩個字形分別編碼。例如:“戶”、“戶”、“戸”三個字。
基於這兩個原則,Unicode 能大幅減少收錄漢字的數量。然而這兩個原則是相互對立的,字源分離原則破壞了認同原則中的“只對字,不對形”編碼之原則,使某些漢字獲得兩個或多個編碼,亦遭受不少批評。例如“値”和“值”。
所以,在 Unicode 1.0 收錄了 20915 個漢字(20902個基本漢字 + 漢字〇 + 12個兼容表意漢字)之後,字源分離原則被放棄。此後,同一字源中不同寫法的漢字,正統的編入正式編碼區,而異體字則編入“兼容表意文字區”。
Unicode 12.1 兼容表意文字編碼區域:
0號平面 F900-FAFF 中日韓兼容表意文字 (CJK Compatibility Ideographs)
2號平面 2F800-2FA1F 中日韓兼容表意文字增補 (CJK Compatibility Ideographs Supplement)
------------------------------------------------------------------------------------------------------------------------------------------
啟示:
1,儘量不要使用Unicode字符集中的兼容表意文字編碼區域,這一點在從PDF文件中複製文字時要尤其注意,在寫程式碼時遇到字串儘量Ctrl+C Ctrl+V
2,使用合適的程式碼字型,有助於你看出字元中的細微差別
3,儘量不要使用Unicode字元作為鍵值
default_name = default_name.replace("⽣", "生") default_name = default_name.replace("⼩", "小") default_name = default_name.replace("⽟", "玉") default_name = default_name.replace("⼤", "大") default_name = default_name.replace("⽉", "月") default_name = default_name.replace("⽜", "牛") default_name = default_name.replace("⾼", "高") default_name = default_name.replace("⼉", "兒") default_name = default_name.replace("⼆", "二") default_name = default_name.replace("⾦", "金") default_name = default_name.replace("⽂", "文") default_name = default_name.replace("⼭", "山") default_name = default_name.replace("⾹", "香") default_name = default_name.replace("⾉", "艮") default_name = default_name.replace("⽴", "立") default_name = default_name.replace("⼋", "八") default_name = default_name.replace("⽥", "田") default_name = default_name.replace("⽕", "火") default_name = default_name.replace("⼦", "子")