我们将路径表示为boost::filesystem::path
,但在某些情况下,其他API期望它们为const char *
(例如,使用SQLite打开数据库文件)。
来自the documentation,path::value_type
是Windows下的wchar_t
。据我所知,Windows wchar_t
是2个字节,UTF-16编码。
有string()
原生观察者返回std::string
,同时说明:
如果string_type是与String不同的类型,则转换为 由cvt。
执行
cvt
初始化为默认构造的codecvt
。这个默认构造的codecvt的行为是什么?
有this forum entry,建议使用utf8_codecvt_facet
的实例作为cvt
值,以便可转换为UTF-8。但似乎这个codecvt实际上是转换between UTF-8 and UCS-4,而不是UTF-16。
获取std::string
的{{1}}表示形式的最佳方法(如果可能的话,可移植)是什么,确保在必要时从正确的path
编码进行转换?
答案 0 :(得分:3)
cvt初始化为默认构造的codecvt。是什么 这个默认构造的codecvt的行为?
它使用默认语言环境转换为特定于语言环境的多字节字符集。在Windows上,此区域设置通常对应于控制面板中的区域设置。
获得最佳方式(如果可能的话,便携式)是什么? std :: string表示路径,确保从中转换 必要时正确编码wchar_t?
C ++ 11标准引入了std::codecvt_utf8_utf16
。虽然从C++17
开始不推荐使用,但根据this paper,它可以使用"直到合适的替代品标准化为止#34;
要使用此方面,请调用静态函数:
boost::filesystem::path::imbue(
std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) );
之后,对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';
}