首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

Windows API 實作 Big5/GB 繁簡中文雙向轉換

     編輯:VC++

前言

在繁體中文 (Big5) 與簡體中文 (GB2312/GBK) 系統間交換資料時,常需進行編碼與字形雙重轉換。Windows 提供 MultiByteToWideChar、WideCharToMultiByte 與 LCMapString 三大 API,串聯即可完成「Big5 → Unicode → GB 繁體 → GB 簡體」完整流程。本文提供可直接部署的 C++ 封裝函數。

核心轉換流程圖

Big5 → [MultiByteToWideChar(CP=950)] → Unicode
                    ↓
GB 繁體 ← [WideCharToMultiByte(CP=936)] ← Unicode
                    ↓
GB 簡體 ← [LCMapString(LCMAP_SIMPLIFIED_CHINESE)] ← GB 繁體

完整代碼(ANSI/MBCS 專案適用)

#include 
#include 
#include 

// 輔助:安全釋放陣列
template 
struct ArrayDeleter { void operator()(T* p) { delete[] p; } };

// Big5 → GB 簡體
std::string Big5ToGbSimplified(const std::string& big5Str)
{
    if (big5Str.empty()) return "";

    // 1. Big5 → Unicode
    int unicodeLen = MultiByteToWideChar(950, 0, big5Str.c_str(), -1, nullptr, 0);
    if (unicodeLen == 0) return "";
    std::unique_ptr> unicodeBuf(new wchar_t[unicodeLen]);
    MultiByteToWideChar(950, 0, big5Str.c_str(), -1, unicodeBuf.get(), unicodeLen);

    // 2. Unicode → GB 繁體 (CP 936)
    int gbLen = WideCharToMultiByte(936, 0, unicodeBuf.get(), -1, nullptr, 0, nullptr, nullptr);
    if (gbLen == 0) return "";
    std::unique_ptr> gbTradBuf(new char[gbLen]);
    WideCharToMultiByte(936, 0, unicodeBuf.get(), -1, gbTradBuf.get(), gbLen, nullptr, nullptr);

    // 3. GB 繁體 → GB 簡體
    std::unique_ptr> gbSimpBuf(new char[gbLen]);
    LCMapString(0x0804, LCMAP_SIMPLIFIED_CHINESE, gbTradBuf.get(), -1, gbSimpBuf.get(), gbLen);

    return std::string(gbSimpBuf.get());
}

// GB 簡體 → Big5
std::string GbSimplifiedToBig5(const std::string& gbSimpStr)
{
    if (gbSimpStr.empty()) return "";

    // 1. GB 簡體 → GB 繁體
    int gbLen = MultiByteToWideChar(936, 0, gbSimpStr.c_str(), -1, nullptr, 0);
    if (gbLen == 0) return "";
    std::unique_ptr> gbTradBuf(new char[gbLen * 2]); // 繁體可能較長
    LCMapString(0x0804, LCMAP_TRADITIONAL_CHINESE, gbSimpStr.c_str(), -1, gbTradBuf.get(), gbLen * 2);

    // 2. GB 繁體 → Unicode
    int unicodeLen = MultiByteToWideChar(936, 0, gbTradBuf.get(), -1, nullptr, 0);
    if (unicodeLen == 0) return "";
    std::unique_ptr> unicodeBuf(new wchar_t[unicodeLen]);
    MultiByteToWideChar(936, 0, gbTradBuf.get(), -1, unicodeBuf.get(), unicodeLen);

    // 3. Unicode → Big5
    int big5Len = WideCharToMultiByte(950, 0, unicodeBuf.get(), -1, nullptr, 0, nullptr, nullptr);
    if (big5Len == 0) return "";
    std::unique_ptr> big5Buf(new char[big5Len]);
    WideCharToMultiByte(950, 0, unicodeBuf.get(), -1, big5Buf.get(), big5Len, nullptr, nullptr);

    return std::string(big5Buf.get());
}

關鍵 API 參數說明

API關鍵參數說明
MultiByteToWideCharCodePage=950/936950=Big5, 936=GBK/GB2312
WideCharToMultiByteCodePage=936/950輸出目標編碼頁
LCMapStringLocale=0x0804 (zh-CN)LCMAP_SIMPLIFIED_CHINESE / LCMAP_TRADITIONAL_CHINESE

Unicode 專案 (CStringW / std::wstring) 簡化版

若專案已設定 Character Set = Use Unicode,可直接使用 CString 簡化:

CString Big5ToGb(const CString& big5)
{
    // Big5 → Unicode
    int len = MultiByteToWideChar(950, 0, big5, -1, NULL, 0);
    CStringW unicode; wchar_t* buf = unicode.GetBuffer(len);
    MultiByteToWideChar(950, 0, big5, -1, buf, len); unicode.ReleaseBuffer();

    // Unicode → GB 簡體 (一次完成:LCMapString 支援 Unicode 輸入)
    len = LCMapString(0x0804, LCMAP_SIMPLIFIED_CHINESE, unicode, -1, NULL, 0);
    CString gbSimp; wchar_t* out = gbSimp.GetBuffer(len);
    LCMapString(0x0804, LCMAP_SIMPLIFIED_CHINESE, unicode, -1, out, len); gbSimp.ReleaseBuffer();
    return gbSimp;
}

注意: LCMapString 在 Unicode 版本可直接處理字形轉換,無需中繼 GB 繁體步驟,但 ANSI 專案必須經過完整三階段。

常見坑與解決方案

  • 緩衝區大小不足: 繁轉簡/簡轉繁字串長度可能變化,建議分配 2x 空間或先呼叫 API 取得長度再配置。
  • 字碼頁不匹配: 確認來源資料真的是 Big5 (CP950) 而非 CP951 (香港補充字集);目標若為 GB18030 仍用 CP936 即可相容。
  • 未定義字元: 部分生僻字在對應字集不存在,API 會轉為預設字元 (通常為 '?'),需業務層面決定是否容忍。
  • 效能優化: 大量文本轉換時,建議重複使用配置緩衝區,避免頻繁 new/delete。

結語

Windows 核心 API 提供完整的字碼頁轉換與字形對應能力,組合 MultiByteToWideChar、WideCharToMultiByte、LCMapString 即可實作健全的繁簡轉換。現代專案建議改用 .NET Encoding.Convert 或 ICU 庫,但在純 C++/MFC 維護專案中,上述封裝函數仍是最輕量、零依賴的解決方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved