我正在尝试使用ICU库来测试字符串是否包含无效的UTF-8字符。我创建了一个utf-8转换器,但没有无效数据给我转换错误。感谢您的帮助。
谢谢, 普拉香特
int main()
{
string str ("AP1120 CorNet-IP v5.0 v5.0.1.22 òÀ MIB 1.5.3.50 Profile EN-C5000");
// string str ("example string here");
// string str (" ����������" );
UErrorCode status = U_ZERO_ERROR;
UConverter *cnv;
const char *sourceLimit;
const char * source = str.c_str();
cnv = ucnv_open("utf-8", &status);
assert(U_SUCCESS(status));
UChar *target;
int sourceLength = str.length();
int targetLimit = 2 * sourceLength;
target = new UChar[targetLimit];
ucnv_toUChars(cnv, target, targetLimit, source, sourceLength, &status);
cout << u_errorName(status) << endl;
assert(U_SUCCESS(status));
}
答案 0 :(得分:4)
我修改了你的程序,打印出之前和之后的实际字符串:
#include <unicode/ucnv.h>
#include <string>
#include <iostream>
#include <cassert>
#include <cstdio>
int main()
{
std::string str("22 òÀ MIB 1");
UErrorCode status = U_ZERO_ERROR;
UConverter * const cnv = ucnv_open("utf-8", &status);
assert(U_SUCCESS(status));
int targetLimit = 2 * str.size();
UChar *target = new UChar[targetLimit];
ucnv_toUChars(cnv, target, targetLimit, str.c_str(), -1, &status);
for (unsigned int i = 0; i != targetLimit && target[i] != 0; ++i)
std::printf("0x%04X ", target[i]);
std::cout << std::endl;
for (char c : str)
std::printf("0x%02X ", static_cast<unsigned char>(c));
std::cout << std::endl << "Status: " << status << std::endl;
}
现在,使用默认编译器设置,我得到:
0x0032 0x0032 0x0020 0x00F2 0x00C0 0x0020 0x004D 0x0049 0x0042 0x0020 0x0031
0x32 0x32 0x20 0xC3 0xB2 0xC3 0x80 0x20 0x4D 0x49 0x42 0x20 0x31
也就是说,输入已经是UTF-8 。这是我的编辑器的一个阴谋,它将文件保存为UTF-8(可在十六进制编辑器中验证),以及将执行字符集设置为UTF-8的GCC。
您可以强制GCC更改这些参数。例如,强制执行字符集为ISO-8859-1(通过-fexec-charset=iso-8859-1
)会产生以下结果:
0x0032 0x0032 0x0020 0xFFFD 0xFFFD 0x0020 0x004D 0x0049 0x0042 0x0020 0x0031
0x32 0x32 0x20 0xF2 0xC0 0x20 0x4D 0x49 0x42 0x20 0x31
如您所见,输入现在是ISO-8859-1编码,转换提示失败并产生“无效字符”代码点U + FFFD。
但是,转换操作仍会返回“成功”状态。看来该库不会将用户数据转换错误视为函数调用的错误。相反,错误状态似乎保留用于空间不足等事情。