c++ - 使用 icu 库将 UTF-8 转换为 UCS-2

标签 c++ unicode utf-8 icu ucs2

我目前正在研究并遇到一个问题,即使用 icu 库将 UTF-8 字符串转换为 UCS-2 字符串。在库中有多种方法可以做到这一点,但到目前为止,它们似乎都没有用,但考虑到这个库的流行,我假设我做错了什么。

首先是公共(public)代码。在所有情况下,我都在一个对象上创建和传递一个字符串,但在它到达转换步骤之前没有任何操作。

当前使用的 utf-8 字符串只是“ĩ”。

为了简单起见,我将在这段代码中将字符串表示为 uniString

UErrorCode resultCode = U_ZERO_ERROR;

UConverter* m_pConv = ucnv_open("ISO-8859-1", &resultCode);

// Change the callback to error out instead of the default            
const void* oldContext;
UConverterFromUCallback oldFromAction;
UConverterToUCallback oldToAction;
ucnv_setFromUCallBack(m_pConv, UCNV_FROM_U_CALLBACK_STOP, NULL, &oldFromAction, &oldContext, &resultCode);
ucnv_setToUCallBack(m_pConv, UCNV_TO_U_CALLBACK_STOP, NULL, &oldToAction, &oldContext, &resultCode);

int32_t outputLength = 0;
int bodySize = uniString.length();
int targetSize = bodySize * 4;
char* target = new char[targetSize];                       

printf("Body: %s\n", uniString.c_str());
if (U_SUCCESS(resultCode))
{
    // outputLength = ucnv_convert("ISO-8859-1", "UTF-8", target, targetSize, uniString.c_str(), bodySize, &resultCode);
    outputLength = ucnv_fromAlgorithmic(m_pConv, UCNV_UTF8, target, targetSize, uniString.c_str(),
        uniString.length(), &resultCode);
    ucnv_close(m_pConv);
}
printf("ISO-8859-1 DGF just tried to convert '%s' to '%s' with error '%i' and length '%i'", uniString.c_str(), 
    outputLength ? target : "invalid_char", resultCode, outputLength);

if (resultCode == U_INVALID_CHAR_FOUND || resultCode == U_ILLEGAL_CHAR_FOUND || resultCode == U_TRUNCATED_CHAR_FOUND)
{
    if (resultCode == U_INVALID_CHAR_FOUND)
    {
        printf("Unmapped input character, cannot be converted to Latin1");                    

        m_pConv = ucnv_open("UCS-2", &resultCode);
        if (U_SUCCESS(resultCode))
        {
            // outputLength = ucnv_convert("UCS-2", "UTF-8", target, targetSize, uniString.c_str(), bodySize, &resultCode);
            outputLength = ucnv_fromAlgorithmic(m_pConv, UCNV_UTF8, target, targetSize, uniString.c_str(),
                uniString.length(), &resultCode);
            ucnv_close(m_pConv);
        }

        printf("UCS-2 DGF just tried to convert '%s' to '%s' with error '%i' and length '%i'", uniString.c_str(), 
            outputLength ? target : "invalid_char", resultCode, outputLength);

        if (U_SUCCESS(resultCode))
        {
            pdus = SegmentText(target, pText, SEGMENT_SIZE_UNICODE_MAX, true);
        }
    }
    else
    {
        printf("DecodeText(): Text contents does not appear to be valid UTF-8");
    }
}
else
{
    printf("DecodeText(): Text successfully converted to Latin1");
    std::string newBody(target, outputLength);
    pdus = SegmentText(newBody, pPdu, SEGMENT_SIZE_MAX);
}

问题是 ucnv_fromAlgorithmic 函数为 ucs-2 转换抛出错误 U_INVALID_CHAR_FOUND。这对 ISO-8859-1 尝试有意义,但对 ucs-2 却没有意义。

另一种尝试是使用 ucnv_convert,您可以看到它已被注释掉。此函数尝试转换,但在 ISO-8859-1 尝试中没有失败,这是应该的。

所以问题是,有没有人有使用这些功能的经验并且看到了不正确的地方,或者关于这个角色的转换假设有什么不正确的地方?

最佳答案

在调用 ucnv_open 之前,您需要将 resultCode 重置为 U_ZERO_ERROR。引自 manual :

“将引用 (C++) 或指针 (C) 指向 UErrorCode 的 ICU 函数首先测试 if(U_FAILURE(errorCode)) { 立即返回;} 因此在这样的函数链中,第一个设置错误码导致后面的不执行任何操作”

关于c++ - 使用 icu 库将 UTF-8 转换为 UCS-2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22209841/

相关文章:

c++ - 使用 C++ 在多维 vector 中分配变量的最佳方法是什么?

c++ - 尝试了解可由 SetProcessMitigationPolicy 函数设置的流程缓解策略

c++ - 为什么 new[] 分配额外的内存?

python - 来自 unicode 字符串的 unicodecsv 阅读器不起作用?

c++ - 在 C++ 或 C++/CX 中检测 Windows Phone 版本

JavaCC 和 Unicode 问题。为什么\u696d属于 "\u4e00"-"\u9fff"范围,但在JavaCC中无法管理

python - 在 Python 中插入 MySQL 时出现 UnicodeEncodeError

php - 字符在 UTF-8 网站上显示不正确

c# - 通过c#/Dapper读取MySQL数据库时utf8字符不正确

java - 同一台机器上不同项目中的控制台输出不正确