中文編碼小知識
GB2312全稱《信息交換用漢字編碼字符集——基本集》,是字符集,收錄了6763個漢字,由國家標準總局1980年3月9號發布,1981年5月1日實施。
GB2312 顯然無法用 1 個位元組表示 1 個字元,所以需要進行編碼。這些漢字加上幾套字母整體無規律的擺放在 94x94 格子里,一行稱為 1 個區,區內一列為 1 個位,其中 16-55 區的高頻漢字是按拼音序排的,56-87 區的次常用字則是按筆劃排的。這種排列管理方式源於 1971 年制定的 ECMA-35 標準,被稱為 code page 。GB2312 要編碼成計算機內存里的數字,最簡單直接的編碼方式就是用區、位序號代表這個字元,這種稱為區位碼。
由於區位碼與 ASCII 字符集有重合,而 ASCII 字符集頭上那些稀奇古怪的字元其實是通信傳輸時的控制字元,為了在通信時不會與控制字元混淆,規定了區碼 +0x20 以避開 ASCII 控制字元的交換碼,這就是 ISO-2022 標準編碼。
EUC-CN 是 Unix 廠商在 ISO-2022 的基礎上制定的,EUC=Extended Unix Code。中英文字元混用實在太常見了,為了方便區分字元到底是中是英,將交換碼位元組最高位置1存儲,這樣GB2312 字元編碼出的位元組值就不會出現在 ASC 區間,這種存儲碼就叫機內碼,簡稱內碼。
GB2312 字符集標準制定之後,除了 EUC-CN,其實還有別的編碼方式,比如斯坦福的李楓峰 1989 搞了 HZ 編碼方式用在 Usenet 和 Email 上。但 EUC-CN 成了主流,今天我們說 GB2312 編碼,基本上就是在說 EUC-CN 編碼的 GB2312 字元。
1987 年有三個被軟體國際化折騰了好些年的傢伙,Joe Backer 在 Xerox,Lee Collins 和 Mark Davis 在蘋果,聯手在1981年以來的多語言系統工作基礎上搞一個大字符集,Joe 把 uni-que/versal/form character encoding 縮成 Unicode,希望它能千秋萬載一統字符集的江湖。到 1993 年 1.1 標準發布時包含 20,902 個漢字。微軟在 1993 年根據 Unicode 對 GB2312 進行擴展形成了 GBK 字符集,該字符集在 Win95、NT3.51 中的實現為 CP936。(*DOS 1.0 以王安字處理機的字符集和ASCII標準為基礎定義了自己的字符集,IBM 1984 年註冊為 CP437 PC-ASC,IBM/M$ 從 1987 年的 PC/MS-DOS 3.3 從引入 CP710 Arabic 開始使用 codepage 機制支持多字符集,1988 年在 DOS 4 里引入 CP936 支持 GB2312-1980,一直沿用下來)
印象里國內中文行業對此挺反感的,實際上 GBK 並不是國家認可的標準,可類比武俠小說作者「金庸著」。Win95 之後見抵抗不能,國家技術監督局標準化司、電子工業部科技與質量監督司發了個文將其公布為「技術規範指導性文件」,也就是現在稱 GBK 1.0 規範的來源。從此埋下了題目里這個問題的禍根呀。
ISO/IECJTCG 兩家在 1991 年開始制定搞大字符集編碼方案,1993 年發布了 ISO-10646,也就是 UCS(Universal Character Set) 方案嘍。GB18030-2000 是在 GBK 的基礎上,結合 ISO-10646 制定的。(話說,在中國政府 2006 年強制要求境內銷售的軟體必須支持 GB18030 之前,其實大家都盡量只用 BMP 平面的字元,這樣就避開了 Sarrogate 問題,字元串操作實現簡單快速,這之後大家都老老實實把 alstral plane 也得搞定。)
Mark Davis 後來在 Taligent 寫了一個庫, 1996 公司被 IBM 收購, 1999 年開源為 Unicode 字符集的 ICU 庫。從歷史文件里可以看到:
- ICU 1.7/2.2 里都包含有標準的 GB2312-1980 文件。
- 2.8 之後出現了 IBM-5479_P100-1995 這個導致了 0x2327 code point 的不同。
- 由 Apple 提供的 CHINSIMP 里則有 0xA1A4, 0xA1AA, 0xA1AB, 0xA1AD, 0xA1E9, 0xA1EA, 0xA3A4, 0xA3FE 這一堆不同。
- SUN jdk1.1.8里的 CP1383 則有 0xA3A7 這個不同;1.3.1時已經在反向查找表裡給 0xA1A4、0xA1AA 加上了不能反查的記錄; 1.5.0 時終於把 0xA1A4、0xA1AA 給徹底改成跟 EUC-CN 不一樣。(IBM 把收購來的 Mark Davis 等人派去給 Java 寫的國際化部分)
這就是 如何評價 iconv 等開源程序採用的 GB 2312 碼錶和 GBK 不完全兼容的情況? 問題的根源嘍。
** 補充一下如今已經成為事實標準的 UTF-8 的背景:
UTF 是 UCS Transformation Format 的縮寫,是將 UCS 編碼方案變成位元組流進行存儲、傳輸的方案。
1992 初, ISO-10646 可選附錄 UTF-1 定義了 32 位 code point,即固定每字元4位元組的編碼方案;
1992-7, X/Open XoJIG 委員會召集更好的編碼方案,Unix 系統實驗室的 Dave Prosser 提交了兼容 7 位 ASCII 的 FSS-UTF,這是一個變長位元組編碼方案;
1992-8 IBM X/Open 代表將 FSS-UTF 展示給多方,Bell 實驗室 Plan9 操作系統組的 Ken Tompson 魔改了一個位元組使用效率略低,但可以直接用第1位元組高位判定字元所用位元組數的方案,並在 9-2 跟 Rob Pike 吃飯時講了一下大概。
1993,Ken Tompson 和 Rob Pike 在 Plane9 里實現並全面使用了這個魔改的 FSS-UTF 方案,然後告訴 X/Open 這個魔改非常成功,於是這個方案就被接受為 FSS-UTF 正式規範了。
1993-1, UTF-8 在 San Diego 召開 USENIX 會議上首次正式亮相。
2003-11,RFC-3629 對 UTF-8 進行了限制,以匹配 UTF-16 的字元編碼限制。
推薦閱讀:
※現在是個普通人,回到過去可能是蓋世英雄呢
※史書里的「某某曰」是直接引用原話還是轉述?
※在中國歷史上強大的漢朝唐朝宋朝等等都曾被少數民族入侵,為何三國時期卻是如此的平靜?
※20 年前就敢賣 40 美金的木頭鉛筆,是什麼鬼?
※國籍與民族,哪個更重要 | 地球知識局