C++ & Boost:编码/解码 UTF-8

Posted

技术标签:

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

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

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

http://www.edobashira.com/2010/03/using-boost-code-facet-for-reading-utf8.html 和 http://www.boost.org/doc/libs/1_46_0/libs/serialization/doc/codecvt.html

尝试将代码转换为使用 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 方面到底出了什么问题? 看看***.com/questions/148403/… wchar_t/wstring 是保存代码点的错误选择,因为根本无法保证 wchar_t 足够宽(iirc,在 Windows 上它不适用于BMP。 【参考方案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!我有一个关于你的图书馆的小问题(顺便说一句,欣赏你在其中付出的优雅和大量的工作!)。你能看一下吗:***.com/questions/49716774/…?

以上是关于C++ & Boost:编码/解码 UTF-8的主要内容,如果未能解决你的问题,请参考以下文章

怎么解决js解码base64中文乱码问题

UTF-7编码

使用 Doctrine 2 强制编码和解码

URL编码与解码

URL编码与解码

URL编码与解码