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

C/C++ UTF-8 字符串清洗:過濾替換無效字節的健壯實現

     編輯:關於C++

問題背景

從網絡/文件讀取的數據可能包含不合法的 UTF-8 字節序列,直接輸出會導致亂碼或解析錯誤。需要一個函數將非法字節替換為安全字符(如 '#'),保證輸出為合法 UTF-8。

UTF-8 編碼規則速查

  • ASCII (1 字節):0xxxxxxx (0x00-0x7F)
  • 2 字節:110xxxxx 10xxxxxx (0xC2-0xDF 開頭)
  • 3 字節:1110xxxx 10xxxxxx 10xxxxxx (0xE0-0xEF 開頭)
  • 4 字節:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (0xF0-0xF4 開頭)
  • 續文字節:10xxxxxx (0x80-0xBF)

狀態機過濾算法

遍歷字節流,維護「預期續文字節數」expect:

  1. 若 expect == 0,判斷當前字節類型,設置 expect 為對應續字節數(0~3)。
  2. 若 expect > 0,檢查是否為合法續字節(0x80-0xBF),合法則 expect--,否則標記從序列起始到當前為非法。
  3. 非法序列整體替換為單個 '#'。
  4. 過濾控制字符(保留 \t\n\r 及可見字符 0x20-0x7E)。

C++ 核心實現

bool filter_utf8(unsigned char* data, size_t len) {
    if (!data) return false;
    size_t expect = 0, seq_start = 0;
    for (size_t i = 0; i < len; ++i) {
        unsigned char c = data[i];
        if (expect == 0) {
            if (c <= 0x7F) {  // ASCII
                if (!(c == '\t' || c == '\n' || c == '\r' || (c >= 0x20 && c <= 0x7E)))
                    data[i] = '#';
            } else if ((c & 0xE0) == 0xC0) expect = 1;      // 2-byte
            else if ((c & 0xF0) == 0xE0) expect = 2;        // 3-byte
            else if ((c & 0xF8) == 0xF0) expect = 3;        // 4-byte
            else { data[i] = '#'; continue; }               // 非法開頭
            seq_start = i;
        } else {
            if ((c & 0xC0) == 0x80) { --expect; }           // 合法續字節
            else {  // 非法續字節,整段標記
                for (size_t j = seq_start; j <= i; ++j) data[j] = '#';
                expect = 0;
                --i;  // 重新檢查當前字節作為新序列開頭
            }
        }
    }
    // 末尾截斷序列
    if (expect > 0) for (size_t j = seq_start; j < len; ++j) data[j] = '#';
    return true;
}

使用示例

std::string s = "\xE4\xB8\xAD\xFF\xE6\x96\x87";  // "中" + 非法 + "文"
filter_utf8((unsigned char*)s.data(), s.size());
// s 變為 "中#文"

總結

單遍歷狀態機即可高效完成 UTF-8 合法性檢查與清洗。關鍵在於正確處理「非法續字節導致整段失效」與「末尾截斷」兩類邊界情況。

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