【问题标题】:C++ & Boost: encode/decode UTF-8C++ & Boost:编码/解码 UTF-8
【发布时间】:2011-09-02 16:05:45
【问题描述】:

我正在尝试做一个非常简单的任务:获取 unicode-aware wstring 并将其转换为 string,编码为 UTF8 字节,然后相反:获取包含 UTF8 的 string字节并将其转换为支持 unicode 的wstring

问题是,我需要它跨平台,我需要它与 Boost 一起工作......我似乎无法找到让它工作的方法。我一直在玩弄

尝试将代码转换为使用 stringstream/wstringstream 而不是任何文件,但似乎没有任何效果。

例如,在 Python 中它看起来像这样:

>>> u"שלום"
u'\u05e9\u05dc\u05d5\u05dd'
>>> u"שלום".encode("utf8")
'\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d'
>>> '\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d'.decode("utf8")
u'\u05e9\u05dc\u05d5\u05dd'

我最终想要的是:

wchar_t uchars[] = {0x5e9, 0x5dc, 0x5d5, 0x5dd, 0};
wstring ws(uchars);
string s = encode_utf8(ws); 
// s now holds "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d"
wstring ws2 = decode_utf8(s);
// ws2 now holds {0x5e9, 0x5dc, 0x5d5, 0x5dd}

我真的不想再增加对 ICU 的依赖或具有这种精神的东西......但据我了解,Boost 应该是可能的。

我们将不胜感激一些示例代码!谢谢

【问题讨论】:

  • imbue 不能与stringstream 一起使用吗? utf8 codecvt 方面到底出了什么问题?
  • wchar_t/wstring 是保存代码点的错误选择,因为根本无法保证 wchar_t 足够宽(iirc,在 Windows 上它不适用于BMP。

标签: c++ boost unicode utf-8


【解决方案1】:

谢谢大家,但最终我求助于http://utfcpp.sourceforge.net/——这是一个非常轻量级且易于使用的纯标题库。我在这里分享一个演示代码,如果有人觉得它有用的话:

inline void decode_utf8(const std::string& bytes, std::wstring& wstr)
{
    utf8::utf8to32(bytes.begin(), bytes.end(), std::back_inserter(wstr));
}
inline void encode_utf8(const std::wstring& wstr, std::string& bytes)
{
    utf8::utf32to8(wstr.begin(), wstr.end(), std::back_inserter(bytes));
}

用法:

wstring ws(L"\u05e9\u05dc\u05d5\u05dd");
string s;
encode_utf8(ws, s);

【讨论】:

    【解决方案2】:

    在 cmets 中已经有一个 boost 链接,但在几乎标准的 C++0x 中,有 wstring_convert 这样做

    #include <iostream>
    #include <string>
    #include <locale>
    #include <codecvt>
    int main()
    {
        wchar_t uchars[] = {0x5e9, 0x5dc, 0x5d5, 0x5dd, 0};
        std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
        std::string s = conv.to_bytes(uchars);
        std::wstring ws2 = conv.from_bytes(s);
        std::cout << std::boolalpha
                  << (s == "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d" ) << '\n'
                  << (ws2 == uchars ) << '\n';
    }
    

    使用 MS Visual Studio 2010 EE SP1 或 CLang++ 2.9 编译时的输出

    true 
    true
    

    【讨论】:

    • 还是不是跨平台的吗? C++11 到来之后?
    • @Mikhail 到了,但是 GCC 还没有实现它。
    • 为了更新答案,到目前为止std::codecvt_utf8std::wstring_convert 和家人是deprecated in C++17。您可以改用std::codecvt
    • @cbuchart 不是真的。为了鼓励 C++20 的替代方案,它们被弃用,别无选择。很像 std::strstream 在 C++98 中被弃用,并且仍然在标准中,别无选择。
    【解决方案3】:

    Boost.Locale 在 Boost 1.48(2011 年 11 月 15 日)中发布,使其更容易从 UTF8/16 转换为 UTF8/16

    以下是文档中的一些方便示例:

    string utf8_string = to_utf<char>(latin1_string,"Latin1");
    wstring wide_string = to_utf<wchar_t>(latin1_string,"Latin1");
    string latin1_string = from_utf(wide_string,"Latin1");
    string utf8_string2 = utf_to_utf<char>(wide_string);
    

    几乎和 Python 编码/解码一样简单 :)

    请注意,Boost.Locale 不是一个只有头文件的库。

    【讨论】:

    • 你能用这个库添加 decode_utf8 操作的例子吗?
    • 你可以试试这个表格把utf-8解码成utf-16 wstring wide_string = to_utf(utf8_bytes,"utf-8");
    【解决方案4】:

    有关处理 utf8 的 std::string/std::wstring直接替换,请参阅 TINYUTF8

    &lt;codecvt&gt; 结合使用,您可以将几乎所有编码从/到utf8 转换为utf8,然后您可以通过上述库处理这些编码。

    【讨论】:

    • 嗨@jakob-riedle!我有一个关于你的图书馆的小问题(顺便说一句,欣赏你在其中付出的优雅和大量的工作!)。你能看一下吗:stackoverflow.com/questions/49716774/…
    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 2011-01-01
    • 2019-09-15
    • 1970-01-01
    • 2021-03-22
    相关资源
    最近更新 更多