Windows 系統內核基於 Unicode (UTF-16)。利用系統 API 實現編碼轉換的標準路徑為:
MultiByteToWideChar → Unicode (Wide-char)WideCharToMultiByte → 目標編碼 (Multi-byte)LCMapString 配合 LCMAP_SIMPLIFIED_CHINESE / LCMAP_TRADITIONAL_CHINESE| 編碼 | 代碼頁 | 常用名稱 |
|---|---|---|
| Big5 (繁體中文) | 950 | CP950 |
| GB2312/GBK (簡體中文) | 936 | CP936 |
| Unicode (系統默認) | 1200 (UTF-16LE) | WideChar |
Big2Gb)AnsiString __fastcall Big2Gb(AnsiString sBig) {
// 1. Big5 → Unicode
char* pszBig5 = sBig.c_str();
int iLen = MultiByteToWideChar(950, 0, pszBig5, -1, NULL, 0);
wchar_t* wszUnicode = new wchar_t[iLen + 1];
MultiByteToWideChar(950, 0, pszBig5, -1, wszUnicode, iLen);
// 2. Unicode → GBK 繁體 (中介)
iLen = WideCharToMultiByte(936, 0, wszUnicode, -1, NULL, 0, NULL, NULL);
char* pszGbTrad = new char[iLen + 1];
WideCharToMultiByte(936, 0, wszUnicode, -1, pszGbTrad, iLen, NULL, NULL);
// 3. GBK 繁體 → GBK 簡體 (核心步驟)
char* pszGbSimp = new char[iLen + 1];
LCMapString(0x0804, LCMAP_SIMPLIFIED_CHINESE, pszGbTrad, -1, pszGbSimp, iLen);
// 4. 清理與返回
AnsiString sGb = pszGbSimp;
delete[] wszUnicode;
delete[] pszGbTrad;
delete[] pszGbSimp;
return sGb;
}
Gb2Big)AnsiString __fastcall Gb2Big(AnsiString sGb) {
// 1. GBK 簡體 → GBK 繁體
char* pszGbSimp = sGb.c_str();
int iLen = MultiByteToWideChar(936, 0, pszGbSimp, -1, NULL, 0);
char* pszGbTrad = new char[iLen * 2 + 1]; // 預留擴展空間
LCMapString(0x0804, LCMAP_TRADITIONAL_CHINESE, pszGbSimp, -1, pszGbTrad, iLen * 2);
// 2. GBK 繁體 → Unicode
wchar_t* wszUnicode = new wchar_t[iLen + 1];
MultiByteToWideChar(936, 0, pszGbTrad, -1, wszUnicode, iLen);
// 3. Unicode → Big5
iLen = WideCharToMultiByte(950, 0, wszUnicode, -1, NULL, 0, NULL, NULL);
char* pszBig5 = new char[iLen + 1];
WideCharToMultiByte(950, 0, wszUnicode, -1, pszBig5, iLen, NULL, NULL);
// 4. 清理與返回
AnsiString sBig5 = pszBig5;
delete[] wszUnicode;
delete[] pszGbTrad;
delete[] pszBig5;
return sBig5;
}
所有 MultiByteToWideChar 和 WideCharToMultiByte 首次調用傳 NULL 緩衝區以獲取所需字符數,再分配內存二次調用實際轉換。這是 Windows API 標準用法,避免緩衝區溢出。
LCMapString 實現簡繁轉換LCMAP_SIMPLIFIED_CHINESE (0x02000000):繁轉簡LCMAP_TRADITIONAL_CHINESE (0x04000000):簡轉繁0x0804 代表中文 (中華人民共和國),此處作為標準簡體中文環境標識使用注意: LCMapString 基於字符映射表,對於「一簡對多繁」或異體字可能無法完美覆蓋,生產環境建議引入專業詞庫庫 (如 OpenCC)。
new[] 分配,delete[] 釋放,嚴格配對std::vector/wstring 自動管理#include
#include
#include
#include
std::string ConvertEncoding(const std::string& src, UINT srcCP, UINT dstCP) {
if (src.empty()) return "";
// Src CP -> UTF-16
int wlen = MultiByteToWideChar(srcCP, 0, src.c_str(), -1, nullptr, 0);
std::vector wbuf(wlen);
MultiByteToWideChar(srcCP, 0, src.c_str(), -1, wbuf.data(), wlen);
// UTF-16 -> Dst CP
int dlen = WideCharToMultiByte(dstCP, 0, wbuf.data(), -1, nullptr, 0, nullptr, nullptr);
std::string dst(dlen, '\0');
WideCharToMultiByte(dstCP, 0, wbuf.data(), -1, &dst[0], dlen, nullptr, nullptr);
if (!dst.empty() && dst.back() == '\0') dst.pop_back(); // 移除結尾空字符
return dst;
}
std::string Big5ToGbSimp(const std::string& big5) {
// Big5 -> GBK Trad
std::string gbkTrad = ConvertEncoding(big5, 950, 936);
// GBK Trad -> GBK Simp (LCMapString 需要寬字符)
int wlen = MultiByteToWideChar(936, 0, gbkTrad.c_str(), -1, nullptr, 0);
std::vector wbuf(wlen);
MultiByteToWideChar(936, 0, gbkTrad.c_str(), -1, wbuf.data(), wlen);
std::vector wout(wlen * 2);
LCMapString(0x0804, LCMAP_SIMPLIFIED_CHINESE, wbuf.data(), -1, wout.data(), wout.size());
// GBK Simp (Wide) -> GBK Simp (Multi-byte)
return ConvertEncoding(std::wstring(wout.data()), 936, 936); // 復用轉換邏輯需微調,此處略
}
利用 Windows 核心 API (MultiByteToWideChar, WideCharToMultiByte, LCMapString) 實現 Big5/GB2312 雙向轉換,無需第三方庫,兼容性極佳。掌握「多位元組 ↔ Unicode ↔ 多位元組」及「LCMapString 簡繁映射」兩大核心模式,即可輕鬆應對中文編碼互轉需求。