【发布时间】:2014-04-09 07:54:49
【问题描述】:
这是a previous one的后续问题
该问题中的问题已解决,现在代码按预期进行,但是 utf-8 到 ucs2 转换的最终输出是乱码。我的意思是最终文本的十六进制值无论如何都与 utf-8 版本不对应。我知道它们是不同的编码,但两者之间似乎没有任何映射。
转换的输入是“ĩ”,输出是“ÿþ)^A”。在十六进制中,“ĩ”(utf-8 值)的值为 c4a9,“ÿþ)^A”(ucs2 值)的值为“00FF 00FE 0029 0001”。
我希望有人对此行为有一个解释,或者可以告诉我我在代码中做错了什么。
新更新的代码是:
UErrorCode resultCode = U_ZERO_ERROR;
UConverter* pLatinOneConv = 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(pLatinOneConv, UCNV_FROU_CALLBACK_STOP, NULL, &oldFromAction, &oldContext, &resultCode);
ucnv_setToUCallBack(pLatinOneConv, 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_fromAlgorithmic(pLatinOneConv, UCNV_UTF8, target, targetSize, uniString.c_str(),
uniString.length(), &resultCode);
ucnv_close(pLatinOneConv);
}
printf("ISO-8859-1 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)
{
resultCode = U_ZERO_ERROR;
printf("Unmapped input character, cannot be converted to Latin1");
// segment Text, if necessary, and add UUIDs copy existing pPdu's addresses and optionals
UConverter* pUscTwoConv = ucnv_open("UCS-2", &resultCode);
if (U_SUCCESS(resultCode))
{
printf("Text Body: %s\n", uniString.c_str());
outputLength = ucnv_fromAlgorithmic(pUscTwoConv, UCNV_UTF8, target, targetSize, uniString.c_str(),
uniString.length(), &resultCode);
ucnv_close(pUscTwoConv);
}
printf("UCS-2 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, pPdu, 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);
}
【问题讨论】:
-
如果您想将 utf8 转换为 ucs2(无论这意味着什么),Latin-1 在您的代码中做了什么?
-
无论如何,U+fffe 是字节顺序标记,U+0129 是带波浪号的 i,因此您的转换至少部分正确。
-
@n.m. Latin1 在那里作为支票。基本上,我们正在测试是否可以先转码为 latin1,如果失败,则失败来自无效字符,我们将其转换为 ucs2。 ucs2 是 utf-16 的另一个名称,至少对于 libicu 而言。
-
我看了一点代码。目前尚不清楚您为什么要尝试
printfUTF-8 编码和 UTF-16 编码的字符串到同一个文件。它不适用于许多有效字符串。你如何看待你的十六进制值?你需要ICU吗?这是一个非常庞大且复杂的库。对于简单的任务libiconv可能更合适。 -
现在一切都将在屏幕输出,我通过获取输出并手动查找所有内容来获取十六进制值。我使用fileformat.info 作为我的参考。你的意思是它不适用于有效的字符串?我知道它存在一些输出问题,但可以对其进行解码。我们在这种情况下使用 icu 作为测试。我们可以选择在我们的软件中进行很多这样的转换。所以 libiconv 可能会让我们度过这个难关,但可能不是其他人。我现在也在质疑这是否不是字节顺序问题。
标签: c++ unicode utf-8 icu ucs2