內碼表

內碼表是字元編碼的別名，也稱內碼錶，是特定語言的字元集的一張表。

歷史

早期，內碼表是 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 小型機。

2.1 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 中，CPACP 與 CPOEMCP 分別表示當前系統的 ANSI 內碼表與 OEM 內碼表。對於 CJK (多位元組編碼) 的環境 (泰文，日文，韓文，中文),CPACP 與 CPOEMCP 沒有區別。對於非 CJK (單位元組編碼) 的環境這兩個內碼表不同。 Windows 的檔案操作的 API 預設使用 ASCII 內碼表 (即 CPACP)，裝置的操作的函式使用 OEM 內碼表 (即 CPOEMCP)。讀寫 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.DefaultChar0);

printf ("Max size of a char: % d\n", info.MaxCharSize);

int i;

const int iMaxLeadBytePairNum = 5;

for (i = 0; i