繁簡中文編碼不相容是跨地區軟體開發常見痛點。大陸採用 GB 碼 (GB2312/GBK),台灣採用 BIG5 碼,雙方編碼對應關係非線性,必須透過碼表查表轉換。本文完整記錄從碼表製作到雙向轉換程式的實作細節。
0x81–0xFE (126 個),第二位元組 0x40–0x7E + 0xA1–0xFE (157 個)0xA440–0xC671 (5,401 字)0xC940–0xF9FE (7,652 字)0xA100–0xFEFF) 寫入二進位檔 Table.txtTable.txt 轉為 GB 碼
// Table.txt 產生程式 (Turbo C++ 3.0)
#include
#include
void main() {
FILE *fp = fopen("table.txt", "wb");
for (int hi = 0xA1; hi <= 0xFE; hi++)
for (int lo = 0x00; lo <= 0xFF; lo++) {
fwrite(&hi, 1, 1, fp);
fwrite(&lo, 1, 1, fp);
}
fclose(fp);
}
關鍵邏輯:將 BIG5 雙位元組映射為碼表線性索引:
if (hi >= 0xA1 && hi <= 0xFE) { // 判斷為漢字首位元組
if (lo >= 0x40 && lo <= 0x7E) // 第二區間
lo = lo - 0x40;
else if (lo >= 0xA1 && lo <= 0xFE) // 第三區間
lo = lo - 0xA1 + 0x7E - 0x40 + 1;
// 線性索引計算
index = (hi - 0xA1) * (0xFE - 0xA1 + 1 + 0x7E - 0x40 + 1) + lo;
// 碼表每項 2 位元組 (GB 碼雙位元組)
fseek(table, 2 * index, SEEK_SET);
fread(&gb_hi, 1, 1, table);
fread(&gb_lo, 1, 1, table);
fwrite(&gb_hi, 1, 1, dest);
fwrite(&gb_lo, 1, 1, dest);
} else {
fwrite(&hi, 1, 1, dest); // ASCII 直通
}
#include
#include
void main() {
int hi, lo;
FILE *src = fopen("big.txt", "rb");
FILE *tab = fopen("table.txt", "rb");
FILE *dst = fopen("gb.txt", "wb");
while (!feof(src)) {
fread(&hi, 1, 1, src);
if (feof(src)) break;
if (hi >= 0xA1 && hi <= 0xFE) {
fread(&lo, 1, 1, src);
if (lo >= 0x40 && lo <= 0x7E) lo = lo - 0x40;
else if (lo >= 0xA1 && lo <= 0xFE) lo = lo - 0xA1 + 0x7E - 0x40 + 1;
fseek(tab, 2 * ((hi - 0xA1) * 157 + lo), SEEK_SET);
fread(&hi, 1, 1, tab);
fread(&lo, 1, 1, tab);
fwrite(&hi, 1, 1, dst);
fwrite(&lo, 1, 1, dst);
} else {
fwrite(&hi, 1, 1, dst);
}
}
fclose(src); fclose(tab); fclose(dst);
}
CFile、fstream、OpenFile)unsigned char table[45840]) 避免頻繁 fseek雖然現代開發多採用 Unicode (UTF-8/UTF-16) 內碼統一避免轉換,但理解雙位元組編碼映射原理、碼表查表機制,對維護舊系統、處理歷史資料、嵌入式資源受限環境仍具實務價值。