使用ICU将UCS-2字符串转换为UTF-8

时间:2014-07-31 09:00:20

标签: c utf-8 utf-16 icu

请帮助我使用ICU将UCS-2字符串转换为UTF-8?

我使用以下代码,但它无法正常工作。

UErrorCode status = U_ZERO_ERROR;
UConverter *conv;
char buf[1000];
int32_t buflen;

conv = ucnv_open("utf-8", &status);

if (U_FAILURE(status))
{
    LOG(L_ERROR, "%s: Can not open the ICU converter\n", __FUNCTION__);
}
else
{
    buflen = ucnv_fromUChars(conv, buf, sizeof(buf), (UChar*)sms->message.s, sms->message.len, &status);

    if (U_FAILURE(status))
    {
        LOG(L_ERROR, "%s: Error in conversion: %s\n", __FUNCTION__, u_errorName(status));
    }
}

LOG(L_DEBUG, "%s: Conversion made ...\n", __FUNCTION__);
hexdump(sms->message.s, sms->message.len);
hexdump(buf, buflen);

sms->消息是一个结构:

typedef struct str
{
    char *s;
    int len;
} str_t;

hexdump打印以下内容(输入文字:" aaaa"):

[DEBUG] add_recv_sms_to_db: Conversion made ...
000000: 00 61 00 61 00 61 00 61                          .a.a.a.a
000000: e6 84 80 e6 84 80 e6 84 80 e6 84 80 00 00 49 00  ..............I.

2 个答案:

答案 0 :(得分:0)

e6 84 80U+6100的UTF-8,是CJK统一表意文字。看起来sms->message.s是小端的,而你的系统是用大端解释它(所以0x0061变成0x6100)。

您可以使用UCNV_UTF16_LittleEndian转换器,或者只是在将sms->message.s传递给ICU之前执行字节交换。

答案 1 :(得分:0)

我不确定它是否与@ecatmur发现的endiannes问题相关联,但您将sms->message.s char*投射到Uchar*

查看here

  

将UChar定义为UCHAR_TYPE,如果是#defined(例如,定义为char16_t),或者将wchar_t定义为16位宽;总是假设没有签名。

     

如果两者都不可用,则将UChar定义为uint16_t。

     

这使得UChar平台依赖的定义允许直接字符串类型与具有16位wchar_t类型的平台兼容。

你确定这个演员是安全的吗?