我在下面编写的这段代码中使用utfcpp从utf16编码的文件转换为utf8字符串。
我认为我一定使用不当,因为结果没有改变。 utf8content
变量每隔一个字符就带有空字符(\0
),就像我放入其中的uft16一样。
//get file content
string utf8content;
std::ifstream ifs(path);
vector<unsigned short> utf16line((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
//convert
if(!utf8::is_valid(utf16line.begin(), utf16line.end())){
utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8content));
}
我发现执行附加操作的库中的位置相同,第一个八位位组中的所有内容均相同,而我认为应该以不同的方式处理0。
这是checked.h的append方法(第106行)。这由
utf16to8
调用(第202行)。请注意,我添加了if的第一部分,以便它跳过null字符以尝试解决问题。template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (!utf8::internal::is_code_point_valid(cp))
throw invalid_code_point(cp);
if(cp < 0x01) //<===I added this line and..
*(result++); //<===I added this line
else if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
我无法想象这是解决方案,只是从字符串中删除null字符,为什么图书馆找不到这个?显然我做错了。
因此,我的问题是,在第一部分代码中实现utfcpp的方式有什么问题?我做错了一些类型转换吗?
我的内容是UTF16编码的xml文件。似乎在第一个空字符处截断了结果。
最佳答案
std::ifstream
以8位char
单位读取文件。 UTF-16改为使用16位单元。因此,如果您要读取文件并使用正确的UTF-16单位填充 vector ,请改用std::wifstream
(如果平台上的std::basic_ifstream<char16_t>
不是16位,则使用wchar_t
或同等功能)。
并且不要在此处调用utf8::is_valid()
。它需要UTF-8输入,但是您可以使用UTF-16输入。
如果sizeof(wchar_t)
为2:
std::wifstream ifs(path);
std::istreambuf_iterator<wchar_t> ifs_begin(ifs), ifs_end;
std::wstring utf16content(ifs_begin, ifs_end);
std::string utf8content;
try {
utf8::utf16to8(utf16content.begin(), utf16content.end(), std::back_inserter(utf8content));
}
catch (const utf8::invalid_utf16 &) {
// bad UTF-16 data!
}
除此以外:
// if char16_t is not available, use unit16_t or unsigned short instead
std::basic_ifstream<char16_t> ifs(path);
std::istreambuf_iterator<char16_t> ifs_begin(ifs), ifs_end;
std::basic_string<char16_t> utf16content(ifs_begin, ifs_end);
std::string utf8content;
try {
utf8::utf16to8(utf16content.begin(), utf16content.end(), std::back_inserter(utf8content));
}
catch (const utf8::invalid_utf16 &) {
// bad UTF-16 data!
}
关于c++ - UTF16转换因utfcpp失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21196393/