如何将 UTF-8 std::string 转换为 UTF-16 std::wstring?

Posted

技术标签:

【中文标题】如何将 UTF-8 std::string 转换为 UTF-16 std::wstring?【英文标题】:How to convert UTF-8 std::string to UTF-16 std::wstring? 【发布时间】:2011-11-01 12:11:16 【问题描述】:

如果我有一个 UTF-8 std::string 如何将其转换为 UTF-16 std::wstring?其实,我想比较两个波斯语单词。

【问题讨论】:

见***.com/questions/148403/…等等。 how can I compare utf8 string such as persian words in c++? 或 this 的可能重复项。 【参考方案1】:

这就是您使用 C++11 的方式:

std::string str = "your string in utf8";
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>> converter;
std::wstring wstr = converter.from_bytes(str);

这些是您需要的标题:

#include <iostream>
#include <string>
#include <locale>
#include <codecvt>

此处提供了更完整的示例: http://en.cppreference.com/w/cpp/locale/wstring_convert/from_bytes

【讨论】:

很好的答案,谢谢! ...但请遵循 cppreference.com 上的示例。 wchar_t 不是 Windows 以外的操作系统上的 16 位类型。您需要改用char16_t @CrisLuengo 谢谢! ? 我更新了答案,改为使用char16_t 不能在 lubuntu 16.04 上使用 g++ 6.2 或 clang++ 3.8 不幸的是,这在 C++17 中已被弃用。 mariusbancila.ro/blog/2018/07/05/…【参考方案2】:

这里有一些代码。仅经过轻微测试,可能会有一些改进。调用此函数将 UTF-8 字符串转换为 UTF-16 wstring。如果它认为输入字符串不是 UTF-8 则抛出异常,否则返回等效的 UTF-16 wstring。

std::wstring utf8_to_utf16(const std::string& utf8)

    std::vector<unsigned long> unicode;
    size_t i = 0;
    while (i < utf8.size())
    
        unsigned long uni;
        size_t todo;
        bool error = false;
        unsigned char ch = utf8[i++];
        if (ch <= 0x7F)
        
            uni = ch;
            todo = 0;
        
        else if (ch <= 0xBF)
        
            throw std::logic_error("not a UTF-8 string");
        
        else if (ch <= 0xDF)
        
            uni = ch&0x1F;
            todo = 1;
        
        else if (ch <= 0xEF)
        
            uni = ch&0x0F;
            todo = 2;
        
        else if (ch <= 0xF7)
        
            uni = ch&0x07;
            todo = 3;
        
        else
        
            throw std::logic_error("not a UTF-8 string");
        
        for (size_t j = 0; j < todo; ++j)
        
            if (i == utf8.size())
                throw std::logic_error("not a UTF-8 string");
            unsigned char ch = utf8[i++];
            if (ch < 0x80 || ch > 0xBF)
                throw std::logic_error("not a UTF-8 string");
            uni <<= 6;
            uni += ch & 0x3F;
        
        if (uni >= 0xD800 && uni <= 0xDFFF)
            throw std::logic_error("not a UTF-8 string");
        if (uni > 0x10FFFF)
            throw std::logic_error("not a UTF-8 string");
        unicode.push_back(uni);
    
    std::wstring utf16;
    for (size_t i = 0; i < unicode.size(); ++i)
    
        unsigned long uni = unicode[i];
        if (uni <= 0xFFFF)
        
            utf16 += (wchar_t)uni;
        
        else
        
            uni -= 0x10000;
            utf16 += (wchar_t)((uni >> 10) + 0xD800);
            utf16 += (wchar_t)((uni & 0x3FF) + 0xDC00);
        
    
    return utf16;

【讨论】:

谢谢!谢谢!它奏效了......我不敢相信:)谢谢你的时间,约翰 真的很高兴它有帮助。这实际上只是提出正确问题的问题。这个论坛上有很多知识,但是新手经常无法访问这些知识,因为他们不知道该问什么。 @aliakbarian:实际上我刚刚在我的代码中发现了一个小错误,您可能应该再次复制它。我把这个if (j == utf8.size()) 改成了这个if (i == utf8.size()) 注意:这仅适用于 Windows。 Unix 系统使用 32 位的 wchar_t Alltho 你仍然可以做 std::wstring wstr(str.begin(), str.end());在 Windows 上。 @coo 当然,这是可能的。如果您的目标是丢弃您的数据。简单地扩展每个 UTF-8 代码单元以适应 UTF-16 代码单元并不会神奇地在这些编码之间进行转换。这只会对输入序列中的任何代码单元产生乱码,而这些代码单元不会恰好编码 ASCII 代码点。【参考方案3】:

有一些相关的问答here和here值得一读。

基本上,您需要将字符串转换为通用格式——我的偏好始终是转换为 UTF-8,但您的里程可能会谨慎。

已经编写了很多用于进行转换的软件——转换是直接的,可以在几个小时内完成——但是为什么不pick up something already done such as the UTF-8 CPP

【讨论】:

如果您仅使用 Windows:msdn.microsoft.com/en-us/library/dd319072(v=VS.85).aspx。否则,请使用便携式库。【参考方案4】:

要在这两种类型之间进行转换,您应该使用:std::codecvt_utf8_utf16< wchar_t> 请注意我用来定义 UTF16 (L) 和 UTF8 (u8) 的字符串前缀。

#include <string>

#include <codecvt>

int main()


    std::string original8 = u8"הלו";

    std::wstring original16 = L"הלו";

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(original16);

    std::wstring utf16NativeString = convert.from_bytes(original8);

    assert(utf8NativeString == original8);
    assert(utf16NativeString == original16);

    return 0;

【讨论】:

【参考方案5】:

Microsoft 为此类转换开发了一个漂亮的库,作为其 Casablanca 项目的一部分,也称为 CPPRESTSDK。这是在命名空间utility::conversions 下标记的。

使用命名空间时,它的简单用法如下所示

utility::conversions

utf8_to_utf16("sample_string");

【讨论】:

【参考方案6】:

这个页面似乎也很有用:http://www.codeproject.com/KB/string/UtfConverter.aspx

在该页面的评论部分,还有一些关于此任务的有趣建议,例如:

// Get en ASCII std::string from anywhere
std::string sLogLevelA = "Hello ASCII-world!";

std::wstringstream ws;
ws << sLogLevelA.c_str();
std::wstring sLogLevel = ws.str();

或者

// To std::string:
str.assign(ws.begin(), ws.end());
// To std::wstring
ws.assign(str.begin(), str.end());

虽然我不确定这些方法的有效性...

【讨论】:

assign() 绝对不是转换 UTF-8UTF-16 的方法。不要在家里尝试这个

以上是关于如何将 UTF-8 std::string 转换为 UTF-16 std::wstring?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 std::string 转换为 NSString?

如何将“char”转换为“std::string”? [复制]

如何将 std::string 转换为 WCHAR

如何将 System::String^ 转换为 std::string?

如何将 std::string 转换为大写? [复制]

如何将 UCHAR 虚拟键代码转换为 std::string [重复]