首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 將 UTF-8 位元組陣列轉為字串:手寫解碼或用 ICU/標準庫 codecvt

     編輯:程式設計綜合問答

輸入位元組:`E4 BD A0 E5 A5 BD E5 91 80 00 72 69 6E 67 3A 20 64 69 73 61 62 6C 65 64` (前 9 字節為「你好呀」UTF-8,後接 ASCII)。

方案一:手寫 UTF-8 解碼器 (教學/無依賴)


std::string utf8_bytes_to_string(const std::vector& bytes) {
    std::string result;
    for (size_t i = 0; i < bytes.size(); ) {
        uint32_t cp = 0;
        int len = 0;
        uint8_t b = bytes[i];
        if ((b & 0x80) == 0) { cp = b; len = 1; }
        else if ((b & 0xE0) == 0xC0) { cp = b & 0x1F; len = 2; }
        else if ((b & 0xF0) == 0xE0) { cp = b & 0x0F; len = 3; }
        else if ((b & 0xF8) == 0xF0) { cp = b & 0x07; len = 4; }
        else { ++i; continue; } // 非法字節跳過
        if (i + len > bytes.size()) break;
        for (int k = 1; k < len; ++k) {
            if ((bytes[i+k] & 0xC0) != 0x80) { cp = 0xFFFD; break; }
            cp = (cp << 6) | (bytes[i+k] & 0x3F);
        }
        // 將 code point 編碼為 UTF-8 追加到 result
        if (cp <= 0x7F) result.push_back(static_cast(cp));
        else if (cp <= 0x7FF) { result.push_back(0xC0 | (cp >> 6)); result.push_back(0x80 | (cp & 0x3F)); }
        else if (cp <= 0xFFFF) { result.push_back(0xE0 | (cp >> 12)); result.push_back(0x80 | ((cp >> 6) & 0x3F)); result.push_back(0x80 | (cp & 0x3F)); }
        else { result.push_back(0xF0 | (cp >> 18)); result.push_back(0x80 | ((cp >> 12) & 0x3F)); result.push_back(0x80 | ((cp >> 6) & 0x3F)); result.push_back(0x80 | (cp & 0x3F)); }
        i += len;
    }
    return result;
}

方案二:C++11 `std::wstring_convert` + `std::codecvt_utf8` (C++17 棄用,C++26 移除)


#include 
#include 
std::string utf8_to_string(const std::vector& bytes) {
    std::wstring_convert> conv;
    std::wstring w = conv.from_bytes(reinterpret_cast(bytes.data()), reinterpret_cast(bytes.data() + bytes.size()));
    // wstring -> string (視平台 wchar_t 寬度)
    return std::string(w.begin(), w.end()); // 簡化,實際需正確轉碼
}

方案三:ICU (International Components for Unicode) — 生產級首選


#include 
std::string utf8_to_string_icu(const uint8_t* src, int32_t srcLen) {
    UErrorCode err = U_ZERO_ERROR;
    UConverter* cnv = ucnv_open("UTF-8", &err);
    int32_t destCap = srcLen * 2; // 足夠大
    std::string dest(destCap, 0);
    int32_t destLen = ucnv_toUnicode(cnv, reinterpret_cast(dest.data()), destCap, reinterpret_cast(src), srcLen, &err);
    dest.resize(destLen * sizeof(UChar));
    ucnv_close(cnv);
    return dest;
}

選型建議

場景推薦
嵌入式/無依賴/教學手寫解碼器 (僅支援 BMP 字元即可)
桌面/伺服器現代 C++17/20ICU (支援完整 Unicode、正規化、邊界分析)
Windows 專用`MultiByteToWideChar(CP_UTF8, ...)` + `WideCharToMultiByte`

原最佳回答提供的十六進位字串解析代碼**邏輯有誤** (索引計算錯誤、未處理多字節),請勿直接使用。

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