使用 std::codecvt_xxx 将 C++ std::wstring 转换为 utf8

Vic*_*rin 4 c++ windows string utf-8 widechar

C ++ 11具有工具宽字符字符串转换std::wstring从/到UTF8表示:std::codecvtstd::codecvt_utf8std::codecvt_utf8_utf16等。

Windows 应用程序可使用哪一个将常规宽字符 Windows 字符串转换std::wstring为 utf8 std::string?它总是在不配置语言环境的情况下工作吗?

Yoc*_*mer 6

取决于你如何转换它们。
您需要指定源编码类型和目标编码类型。
wstring不是一种格式,它只是定义了一种数据类型。

现在通常当人们说“Unicode”时,意思UTF16Microsoft Windows使用的内容,通常是wstring包含的内容。

因此,从 UTF8 转换为 UTF16 的正确方法是:

     std::string utf8String = "blah blah";

     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
     std::wstring utf16String = convert.from_bytes( utf8String );
Run Code Online (Sandbox Code Playgroud)

反过来说:

     std::wstring utf16String = "blah blah";

     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
     std::string utf8String = convert.to_bytes( utf16String );
Run Code Online (Sandbox Code Playgroud)

更令人困惑的是:
当您std::stringWindows平台上使用时(例如使用多字节编译时),它不是UTF8。他们使用ANSI
更具体地说,您的 Windows 使用的默认编码语言。

另外,请注意wstring 与 UTF-16 并不完全相同

当以 Unicode 编译时,windows API 命令需要这些格式:

命令A -多字节-ANSI
命令W - Unicode -UTF16

  • *“通常当一个人说“Unicode”时,意味着 UTF16”* - 嗯...当一个人说“Unicode”时,我希望人们了解 Unicode,并且不要将标准与任意编码混淆。*“当您在 Windows 平台上使用 std::string 时 [...],它不是 UTF8。他们使用 ANSI。”* - 用于 `std::string` 的字符编码由实现(即编译器)决定,而不是目标平台。您可以编写一个在 Windows 上对“std::string”使用 UTF-8 编码的编译器。 (2认同)

Vic*_*rin 3

似乎对于转换->std::codecvt_utf8效果很好。它通过了我所有的测试。(Windows 应用程序、Visual Studio 2015、带 EN 区域设置的 Windows 8)std::wstringutf8

\n\n

我需要一种将文件名转换为 UTF8 的方法。因此我的测试是关于文件名的。

\n\n

在我的应用程序中,我使用boost::filesystem::path1.60.0 来处理文件路径。它运行良好,但无法正确将文件名转换为 UTF8。\nWindows 版本内部boost::filesystem::path使用std::wstring存储文件路径。不幸的是,内置转换std::string效果不佳。

\n\n

测试用例:

\n\n
    \n
  • 创建包含混合符号的文件c:\\test\\\xe7\x9a\x80\xe7\x9a\x81\xe7\x9a\x82\xe7\x9a\x83\xe7\x9a\x84(一些随机的亚洲符号)
  • \n
  • 扫描目录boost::filesystem::directory_iterator,获取boost::filesystem::path文件
  • \n
  • 将其转换为std::stringvia内置转换filenamePath.string()
  • \n
  • 你得到c:\\test\\?????。亚洲符号转换为\'?\'。不好。
  • \n
\n\n

boost::filesystem内部使用std::codecvt。它不适用于转换std::wstring-> std::string

\n\n

boost::filesystem::path您可以将转换函数定义为以下形式(原始片段) ,而不是内置转换:

\n\n
std::string utf8_to_wstring(const std::wstring & str)\n{\n    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;\n    return myconv.to_bytes(str);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后您可以轻松地将文件路径转换为 ​​UTF8:utf8_to_wstring(filenamePath.wstring())。它工作完美。

\n\n

它适用于任何文件路径。我测试了 ASCII 字符串c:\\test\\test_file、亚洲字符串、c:\\test\\\xe7\x9a\x80\xe7\x9a\x81\xe7\x9a\x82\xe7\x9a\x83\xe7\x9a\x84俄语字符串c:\\test\\\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4、混合字符串c:\\test\\test_\xe7\x9a\x80\xe7\x9a\x81\xe7\x9a\x82\xe7\x9a\x83\xe7\x9a\x84、、c:\\test\\test_\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4c:\\test\\test_\xe7\x9a\x80\xe7\x9a\x81\xe7\x9a\x82\xe7\x9a\x83\xe7\x9a\x84_\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4对于每个字符串,我都会收到有效的 UTF8 表示形式。

\n