在Windows上获取boost :: filesystem :: path作为UTF-8编码的std :: string

Ad *_*d N 7 c++ encoding utf-8 boost-filesystem

我们将路径表示为boost::filesystem::path,但在某些情况下,其他API期望它们const char *(例如,使用SQLite打开DB文件).

文档中,path::value_type是一个wchar_tWindows下.据我所知,Windows wchar_t是2字节,UTF-16编码.

有一个string()原生观察者返回一个std::string,同时说明:

如果string_type是与String不同的类型,则转换由cvt执行.

cvt被初始化为默认构造codecvt.这个默认构造的codecvt的行为是什么?

这个论坛条目,建议使用一个实例utf8_codecvt_facet作为cvt值可移植转换为UTF-8.但似乎这个codecvt实际上是在UTF-8和UCS-4之间转换,而不是UTF-16.

什么是最好的方式(如果可能的话,便携式)获得a的std::string表示path,确保wchar_t在必要时从正确的编码转换?

zet*_*t42 7

cvt 被初始化为默认构造的 codecvt。这个默认构造的 codecvt 的行为是什么?

它使用默认语言环境转换为特定于语言环境的多字节字符集。在 Windows 上,此区域设置通常对应于控制面板中的区域设置。

获得路径的 std::string 表示的最佳方式(如果可能的话)是什么,确保在必要时从正确的 wchar_t 编码转换?

C++11 标准引入了std::codecvt_utf8_utf16. 尽管它自 起已被弃用C++17,但根据本文,它将在“直到合适的替代品标准化”之前可用。

要使用此方面,请调用静态函数:

boost::filesystem::path::imbue( 
    std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) );
Run Code Online (Sandbox Code Playgroud)

之后所有调用path::string()都将从 UTF-16 转换为 UTF-8。

另一种方法是使用std::wstring_convert< std::codecvt_utf8_utf16<wchar_t> >仅在某些情况下进行转换。

完整示例代码:

#include <boost/filesystem.hpp>
#include <iostream>
#include <codecvt>

void print_hex( std::string const& path );

int main()
{
    // Create UTF-16 path (on Windows) that contains the characters "ÄÖÜ".
    boost::filesystem::path path( L"\u00c4\u00d6\u00dc" );

    // Convert path using the default locale and print result.
    // On a system with german default locale, this prints "0xc4 0xd6 0xdc".
    // On a system with a different locale, this might fail.
    print_hex( path.string() );

    // Set locale for conversion from UTF-16 to UTF-8.
    boost::filesystem::path::imbue( 
        std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) );

    // Because we changed the locale, path::string() now converts the path to UTF-8.
    // This always prints the UTF-8 bytes "0xc3 0x84 0xc3 0x96 0xc3 0x9c".
    print_hex( path.string() );

    // Another option is to convert only case-by-case, by explicitly using a code converter.
    // This always prints the UTF-8 bytes "0xc3 0x84 0xc3 0x96 0xc3 0x9c".
    std::wstring_convert< std::codecvt_utf8_utf16<wchar_t> > cvt;
    print_hex( cvt.to_bytes( path.wstring() ) );
}

void print_hex( std::string const& path )
{
    for( char c : path )
    {
        std::cout << std::hex << "0x" << static_cast<unsigned>(static_cast<unsigned char>( c )) << ' ';
    }
    std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)

  • 这个 `path.imbue` 调用具有误导性 - `boost::filesystem::path::imbue` 是一个影响全局状态的静态函数,而不是 `path` 变量本身。 (2认同)