Java 預設 UTF-8,VC++ 預設 GB2312,XML 通訊雙端編碼不一致導致中文亂碼。核心解法:UTF-8 ↔ Unicode ↔ GB2312 雙向轉換,利用 WinAPI WideCharToMultiByte / MultiByteToWideChar。
// 寬字元 → 多位元組 (Unicode → ANSI/GB2312/UTF-8)
int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte,
LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
// 多位元組 → 寬字元 (ANSI/GB2312/UTF-8 → Unicode)
int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
CP_ACP:系統預設 ANSI 碼頁(中文環境為 GB2312/CP936)。CP_UTF8:UTF-8 碼頁(WinAPI 直接支援)。
// 16進位字元 → 4位元二進位字串
CString HexToBin(CString s) { /* switch 表查 '0'~'f' → "0000"~"1111" */ }
// 4位元二進位字串 → 16進位字元
CString BinToHex(CString s) { /* 反向查表 */ }
// 8位元二進位字串 → 整數
int BinToInt(CString s) { /* 位權加總 */ }
WCHAR* UTF_8ToUnicode(char* utf8Ptr) {
// 取 UTF-8 三位元組
BYTE b1 = utf8Ptr[0], b2 = utf8Ptr[1], b3 = utf8Ptr[2];
// 解析位元模式:1110xxxx 10yyyyyy 10zzzzzz → Unicode: xxxxyyyy yyzzzzzz
CString bin = HexToBin(b1).Right(4) + HexToBin(b2).Right(6) + HexToBin(b3).Right(6);
// 取高低位元組
int hi = BinToInt(bin.Left(8));
int lo = BinToInt(bin.Right(8));
WCHAR wch = (hi << 8) | lo;
return &wch; // 注意:實際需動態配置記憶體
}
char* UnicodeToGB2312(WCHAR wch) {
char* buf = new char[2];
WideCharToMultiByte(CP_ACP, 0, &wch, 1, buf, 2, NULL, NULL);
return buf;
}
WCHAR* GB2312ToUnicode(char* gbPtr) {
WCHAR* wch = new WCHAR;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbPtr, 2, wch, 1);
return wch;
}
char* UnicodeToUTF_8(WCHAR wch) {
// Unicode 16-bit → UTF-8 三位元組編碼
int hi = wch >> 8, lo = wch & 0xFF;
CString bin = HexToBin(hi).Right(8) + HexToBin(lo).Right(8); // 16 位元
// 切分:xxxxyyyy yyzzzzzz → 1110xxxx 10yyyyyy 10zzzzzz
CString utf8bin = "1110" + bin.Mid(0,4) + "10" + bin.Mid(4,6) + "10" + bin.Mid(10,6);
char* buf = new char[3];
buf[0] = BinToInt(utf8bin.Left(8));
buf[1] = BinToInt(utf8bin.Mid(8,8));
buf[2] = BinToInt(utf8bin.Right(8));
return buf;
}
char* TranslateToUTF_8(char* gbStr, int len) {
char* out = new char[len * 3 + 1]; // 最坏情况每中文字符变3字节
int inPos = 0, outPos = 0;
while (inPos < len) {
if ((BYTE)gbStr[inPos] < 0x80) { // ASCII 直接複製
out[outPos++] = gbStr[inPos++];
} else { // 中文字符:2 bytes GB2312 → 3 bytes UTF-8
WCHAR* w = GB2312ToUnicode(gbStr + inPos);
char* u = UnicodeToUTF_8(*w);
memcpy(out + outPos, u, 3);
outPos += 3; inPos += 2;
delete w; delete[] u;
}
}
out[outPos] = '\0';
return out;
}
MultiByteToWideChar(CP_UTF8, ...) 直接處理 UTF-8,避免手工位元操作。std::wstring_convert / std::codecvt_utf8(C++17 棄用)或第三方庫(ICU、utf8cpp)更健壯。掌握 UTF-8 ↔ Unicode ↔ GB2312 轉換鏈路與 WinAPI 正確參數,可解決跨平台中文編碼互通難題。建議新專案全面採用 UTF-8 統一編碼,減少轉換層複雜度。