我正在尝试使用ICU库来测试字符串是否包含无效的UTF-8字符。我创建了一个UTF-8转换器,但是没有无效数据给我一个转换错误。感谢你的帮助。
谢谢,Prashanth
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));
}
Run Code Online (Sandbox Code Playgroud)
我修改了您的程序,以在之前和之后打印出实际的字符串:
#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;
}
Run Code Online (Sandbox Code Playgroud)
现在,使用默认的编译器设置,我得到:
0x0032 0x0032 0x0020 0x00F2 0x00C0 0x0020 0x004D 0x0049 0x0042 0x0020 0x0031
0x32 0x32 0x20 0xC3 0xB2 0xC3 0x80 0x20 0x4D 0x49 0x42 0x20 0x31
Run Code Online (Sandbox Code Playgroud)
也就是说,输入已经是UTF-8。这是我的编辑器的阴谋,该编辑器将文件保存为UTF-8(可在十六进制编辑器中验证),而GCC的设置是将执行字符集设置为UTF-8。
您可以强制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
Run Code Online (Sandbox Code Playgroud)
如您所见,输入现在已被ISO-8859-1-编码,并且转换迅速失败并产生“无效字符”代码点U + FFFD。
但是,转换操作仍返回“成功”状态。看来该库没有将用户数据转换错误视为函数调用错误。相反,错误状态似乎是为空间不足之类的情况保留的。