You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ICU验证GB2312编码时遇65533提前停止并报错?

如何让ICU在遇到无效GB2312字节时停止转换并报错?

我想使用ICU验证字节流是否采用GB2312编码,编写了如下C++代码:

bool is_gb2312(char *data, size_t len) {
    UErrorCode status = U_ZERO_ERROR;

    UConverter* conv = ucnv_open("GB2312", &status);
    if (U_FAILURE(status)) {
        std::cerr << "ucnv_open failed" << std::endl;
        return false;
    }

    auto* output = new UChar[len * 2];
    UChar* target = output;

    char const* source = data;
    ucnv_toUnicode(conv, &target, output + len * 2, &source, data + len, nullptr, true, &status);

    if (U_FAILURE(status)) {
        std::cerr << "ucnv_toUnicode failed" << std::endl;
        return false;
    }

    delete[] output;
    ucnv_close(conv);
    return true;
}

但发现即使存在无效字节(如0xA1 0xA0),ICU也不会报错,仅将其转换为65533替换字符。请问如何让ICU在遇到65533时提前停止并上报错误?

解决方案

ICU默认采用替换字符处理无效输入,要实现遇到无效字节时立即停止转换并报错,只需修改转换器的错误处理模式:

关键修改步骤

  1. 设置错误处理行为为UCNV_STOP_ON_ERROR
    在打开转换器成功后,调用ucnv_setErrorAction函数,指定遇到无效输入时停止转换并触发错误:

    ucnv_setErrorAction(conv, UCNV_STOP_ON_ERROR, UCNV_STOP_ON_ERROR, &status);
    

    该函数的两个UCNV_STOP_ON_ERROR参数分别控制"从Unicode转换"和"到Unicode转换"的错误行为,这里我们只需要后者生效,但统一设置更稳妥。

  2. 完整修改后的代码

    bool is_gb2312(char *data, size_t len) {
        UErrorCode status = U_ZERO_ERROR;
    
        UConverter* conv = ucnv_open("GB2312", &status);
        if (U_FAILURE(status)) {
            std::cerr << "ucnv_open failed" << std::endl;
            return false;
        }
    
        // 配置错误处理:遇到无效字节立即停止并上报错误
        ucnv_setErrorAction(conv, UCNV_STOP_ON_ERROR, UCNV_STOP_ON_ERROR, &status);
        if (U_FAILURE(status)) {
            std::cerr << "ucnv_setErrorAction failed" << std::endl;
            ucnv_close(conv);
            return false;
        }
    
        auto* output = new UChar[len * 2];
        UChar* target = output;
        char const* source = data;
    
        ucnv_toUnicode(conv, &target, output + len * 2, &source, data + len, nullptr, true, &status);
    
        bool isValid = U_SUCCESS(status);
        if (U_FAILURE(status)) {
            std::cerr << "ucnv_toUnicode failed: " << u_errorName(status) << std::endl;
        }
    
        delete[] output;
        ucnv_close(conv);
        return isValid;
    }
    

说明

  • UCNV_STOP_ON_ERROR会让ICU在检测到无效输入字节时立刻终止转换,并将status设置为具体错误码(例如U_INVALID_CHAR_FOUND)。
  • 必须在调用ucnv_toUnicode之前配置错误处理行为,否则不会生效。
  • 使用u_errorName(status)可以输出具体错误名称,便于调试定位问题。

内容的提问来源于stack exchange,提问作者chenzhongpu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 06:55:58