GBK 編碼下,漢字佔 2 字節,首字節高位為 1(≥ 0x81),尾字節範圍 0x40–0xFE(含 0x48 'H')。單字節讀取時,尾字節會被誤判為 ASCII 字符,導致「錒」(0xE5 0x48) 後半字節 0x48 被當作 'H' 寫入拼音串。
while (!ifs.eof()) {
ifs.read(&word, 1);
if (isChineseLeadByte(word)) { // 1. 先判斷是否為漢字首字節
char byte2;
ifs.read(&byte2, 1); // 2. 直接讀取尾字節,組成完整漢字
chinese = string(1, word) + byte2; // 3. 確信是漢字,無需二次判斷
// 處理漢字-拼音映射...
}
else if (isLetterOrNumber(word)) { // 4. 排除漢字後,再處理 ASCII
pinyin += word;
}
// 其他控制字符處理...
}
bool isChineseLeadByte(unsigned char c) {
// GBK: 0x81-0xFE 為首字節範圍(排除 0x7F 控制字符)
return c >= 0x81 && c <= 0xFE;
}
// UTF-8 版本(首字節高位模式)
bool isUTF8LeadByte(unsigned char c) {
return (c & 0x80) != 0; // 1xxxxxxx 為多字節序列首字節
}
// 原邏輯錯誤:逐字節判斷,尾字節 0x48 被誤判為 'H'
// 修正:檢測到首字節 → 強制讀取下一字節組合 → 確認為漢字
if (isChineseLeadByte(word)) {
char next;
ifs.read(&next, 1);
string hanzi; hanzi += word; hanzi += next;
table[hanzi] = pinyin;
ofs.write(hanzi.c_str(), 2);
ofs.write(pinyin.c_str(), pinyin.size());
ofs.write("\r\n", 2);
chinese.clear();
pinyin.clear(); // 重置拼音緩衝
}
else if (isLetterOrNumber(word)) {
pinyin += word;
}
else if (word == '\r') {
ifs.read(&word, 1); // 吞掉 \n
pinyin.clear();
}
「多字節編碼下,必須按字符邊界讀取,而非按字節逐個判斷。」
檢測到 Lead Byte → 原子性讀取完整字符 → 語義處理,中間不插入單字節判斷邏輯。
掌握「首字節特徵 → 整體讀取 → 語義處理」三步法,GBK/UTF-8/Big5 等所有多字節編碼文本解析都能游刃有餘。