首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UTF16转换失败

UTF16转换失败
EN

Stack Overflow用户
提问于 2014-01-17 21:38:39
回答 2查看 462关注 0票数 2

下面我编写了一些代码,使用utfcpp将utf16编码的文件转换为utf8字符串。

我想我一定是不恰当地使用它,因为结果并没有改变。utf8content变量带有空字符(\0),每个其他字符都与我放入的uft16完全相同。

代码语言:javascript
复制
//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中的附加方法(第106行)。这是由utf16to8调用的(第202行)。注意,我添加了if的第一部分,这样它就跳过了空字符,试图修复这个问题。

代码语言:javascript
复制
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;
}

但是,我无法想象这是解决方案,只是从字符串中删除空字符,为什么库没有找到这个呢?所以很明显我做错了什么。

所以,我的问题是,我在第一段代码中实现utfcpp的方式有什么问题?我做错了什么类型转换吗?

我的内容是一个UTF16编码的xml文件。它似乎截断了第一个空字符的结果。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-17 23:11:40

std::ifstream以8位char单元读取文件。16使用16位单位代替。因此,如果您想读取该文件并使用适当的UTF-16单元填充您的向量,则使用std::wifstream (或者std::basic_ifstream<char16_t>或如果wchar_t在您的平台上不是16位)。

这里也不要给utf8::is_valid()打电话。它期望UTF-8输入,但您有UTF-16输入。

如果sizeof(wchar_t)为2:

代码语言:javascript
复制
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!
}

否则:

代码语言:javascript
复制
// 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!
}
票数 2
EN

Stack Overflow用户

发布于 2014-01-17 22:45:43

问题在于您在哪里读取该文件:

代码语言:javascript
复制
vector<unsigned short> utf16line((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

这一行使用一个char迭代器,并使用它一次填充一个向量。您实际上是在转换每个字节,而不是一次读取两个字节。

这是将每个UTF-16实体分成两个部分,对于大部分输入来说,这两个部分中的一个将是空字节。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21196393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档