頁碼

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

## 歷史

早期，頁碼是 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）

## 其他代碼頁

* 10000—Macintosh Roman encoding（followed by several other Mac character sets）
* 10007—Macintosh Cyrillic encoding
* 10029—Macintosh Central European encoding
* 1200—UCS-2LE Unicode 小端序
* 1201—UCS-2BE Unicode 大端序
* 65000—UTF-7 Unicode
* 65001—UTF-8 Unicode

## 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()` 給出指定的頁碼的資訊。如東亞多位元組頁碼的預設字元、前導位元組的範圍：

## 外部連結

* 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（頁面存檔備份，存於網際網路檔案館）