代碼頁
歷史
編輯早期,代碼頁是IBM稱呼計算機的BIOS所支持的字符集編碼。當時通用的操作系統都是命令行界面,這些操作系統直接使用BIOS提供的字符繪製功能來顯示字符(或者是一組嵌入在顯卡字符生成器中的字形)。這些BIOS代碼頁也被稱為OEM代碼頁。圖形操作系統使用自己的字符呈現引擎(rendering engine),可以支持多個不同的字符集編碼,這類代碼頁被稱作ANSI代碼頁。
早期IBM和微軟內部使用數字來標記不同的編碼字符集,不同的廠商對同一個字符集編碼使用各自不同的名稱。例如,UTF-8在IBM稱作代碼頁1208,在微軟稱作代碼頁65001,在SAP稱作代碼頁4110。
1987年4月,IBM發布了PC-DOS 3.3,正式開始使用16比特的無符號整數標識不同的代碼頁。這時的PC機使用CGA顯示系統的字符界面,繪製不同語言的字符依靠BIOS硬件廠商(在當時就是指制定業界標準的IBM)提供的功能。如果想更換所支持的字符集,就必須換上支持該字符集的ROM芯片。微軟作為DOS操作系統的軟件廠商,並不擁有繪製這些字符集的知識產權。所以這些字符集的繪製實現,稱作OEM代碼頁。最常見、最具代表性的OEM代碼頁是"IBM PC或MS-DOS 代碼頁437"。
隨着圖形用戶界面操作系統的廣泛使用(最初被廣為接受的是Windows 3.1),操作系統具有了字符繪製的功能。微軟在Windows操作系統沒有轉向UTF-16作為內碼實現之前(也就是在Windows 2000之前),針對不同的使用地區與國家,定義了一系列的支持不同語言字符集的代碼頁,被稱作"Windows(或ANSI)代碼頁"。代表性的是實現了ISO-8859-1的代碼頁1252。
OEM(IBM PC)代碼頁
編輯- 437—最初的IBM PC代碼頁,實現了擴展ASCII字符集
- 737—希臘語
- 850—「多語言(Latin-1)」(西歐語言)
- 852—「斯拉夫(Latin-2)」(中歐及東歐語言)
- 855—西里爾(Cyril)字母
- 857—土耳其語
- 858—帶歐元符號的「多語言」
- 860—葡萄牙語
- 861—冰島語
- 863—法語加拿大英語
- 865—北歐
- 866—西里爾(Cyril)字母
- 869—希臘語
代碼頁819實現了Latin-1(ISO/IEC 8859-1),用於IBM AS/400小型機。
OEM代碼頁轉換為ASCII代碼頁
編輯對於中日韓的多字節編碼的代碼頁,OEM代碼頁與ASCII代碼頁相同,例如對於簡體中文的OEM代碼頁與ASCII代碼頁就是GBK代碼頁。而對於單字節編碼的代碼頁,如英語、俄語等,OEM代碼頁與ASCII代碼頁一般不同。這是因為在MS-DOS時代,計算機只能使用字符界面在屏幕上畫出表格的框線,所以OEM代碼頁要在單字節字符集中包含方框繪製字符;此外,OEM代碼頁437提供的有限的變音符號,只能覆蓋法語、西班牙語、德語、意大利語、瑞典語的字母表。而在Windows的早期時代,仍然使用單字節字符集,這時就捨棄了這些不必要的方框繪製字符,取而代之的是丹麥語、挪威語、冰島語、加拿大法語的變音符號。為此,一個用OEM代碼頁的字節流要在Windows上正確顯示,就需要或者顯式設定使用OEM代碼頁;或者要顯式把OEM代碼頁的字節流轉化為ASCII代碼頁的字符流,這需要使用Windows系統調用OemToChar()
。
Windows(ANSI)代碼頁
編輯Windows代碼頁最初是根據ANSI草案實現的,這個草案最終成為ISO 8859-1。這是Windows代碼頁被稱作ANSI的緣由。
- 874—泰文字母
- 1250—東歐拉丁字母
- 1251—古斯拉夫語
- 1252—西歐拉丁字母ISO-8859-1.
- 1253—希臘語
- 1254—土耳其語
- 1255—希伯來語
- 1256—阿拉伯語
- 1257—巴爾
- 1258—越南
Windows-1252與ISO-8859-1並不完全一致。ISO-8859-1在0x80-0x9F範圍的控制字符,在Windows-1252中被可打印字符取代。由於在web網頁中,ASCII控制字符不起作用,所以網頁一般用Windows-1252代碼頁標記替代ISO-8859-1標記。
中日韓語言代碼頁
編輯既是OEM代碼頁,也是Windows代碼頁。
- 936—簡體中文(GBK)
- 950—繁體中文(大五碼)
- 932—日文(Shift_JIS)
- 949—韓文(EUC-KR)
- 20000(CNS)以EUC編碼的繁體中文CNS編碼
- 20002(Eten)以EUC編碼的繁體中文倚天碼
- 20936(GB2312-80)以EUC編碼的簡體中文GB2312編碼(老設備或嵌入式設備常見)
- 50227(ISO-2022-GB)簡體中文的Esc序列編碼,純ASCII
- 50229(ISO-2022-CNS)繁體中文的Esc序列編碼,純ASCII
- 52936(HZ-GB-2312)以~{和~}分隔的簡體中文GB2312編碼,純ASCII
- 54936—簡體中文(GB18030)
其他代碼頁
編輯Windows操作系統中使用的代碼頁
編輯Windows平台上的GUI程序使用ANSI代碼頁,而在控制台程序使用OEM代碼頁(以便向後兼容)。這意味着,如果在記事本程序(notepad.exe)打開一個8位字符集編碼的文本文件,將使用ANSI代碼頁;如果在命令行中用type命令顯示這個文本文件的內容,將使用OEM代碼頁。這兩個代碼頁在前128個字符的編碼是一樣的,但後128個字符的編碼可能不一致。在Windows的命令行窗口通過標記、複製操作把一部分文本內容複製到記事本程序中,實際上是把Unicode格式的內容保存在剪貼板,使得這種文本複製保持了字符編碼的透明轉換。
對於Windows操作系統中的命令行窗口(Command Prompt),chcp命令在沒有參數時,顯示當前代碼頁;chcp命令帶一個整數參數,則改變命令行窗口的當前代碼頁為參數所指定。
把UTF-8編碼文本直接寫到控制台,必須先使用函數SetConsoleOutputCP(65001),然後使用puts一族的函數來輸出文本。把UTF-8編碼文本寫入UTF-8文件時,可以直接使用窄字符輸出函數。
在Windows API中,CP_ACP與CP_OEMCP分別表示當前系統的ANSI代碼頁與OEM代碼頁。對於CJK(多字節編碼)的環境(泰文,日文,韓文,中文),CP_ACP與CP_OEMCP沒有區別。對於非 CJK(單字節編碼)的環境這兩個代碼頁不同。 Windows的文件操作的API默認使用ASCII代碼頁(即CP_ACP),設備的操作的函數使用OEM代碼頁(即CP_OEMCP)。讀寫console的函數是對console設備的操作,所以默認使用OEMCP。
查詢代碼頁的信息
編輯Windows系統調用GetCPInfo()
給出指定的代碼頁的信息。如東亞多字節代碼頁的缺省字符、前導字節的範圍:
{
CPINFO info;
UINT iCP = 932; //GBK
GetCPInfo(iCP, &info);
printf("Code page %d's default char is [%c]\n", iCP, info.DefaultChar[0]);
printf("Max size of a char: %d\n", info.MaxCharSize);
int i;
const int iMaxLeadBytePairNum = 5;
for (i = 0; i < iMaxLeadBytePairNum; i++)
{
if (info.LeadByte[i * 2] == 0 && info.LeadByte[i * 2 + 1] == 0)
break;
printf("Lead byte pair %d: 0x%02X-0x%02X\n", i, info.LeadByte[i * 2], info.LeadByte[i * 2 + 1]);
}
}
外部連結
編輯- IBM代碼頁(英文)
- IBM/ICU Charset Information
- Microsoft code page identifiers(Microsoft's list contains only code pages actively used by normal apps on Windows see also Torsten Mohrin's list for the full list of supported code pages)
- Shorter Microsoft list containing only the ANSI and OEM code pages but with links to more detail on each
- Character Sets And Code Pages At The Push Of A Button(頁面存檔備份,存於網際網路檔案館)