Visual Studio 2017中的UTF-8支持std :: experimental :: filesystem :: path

时间:2018-04-03 22:21:10

标签: c++ unicode utf-8 visual-studio-2017 c++-experimental

我很高兴看到在Visual Studio 2017中添加了对std::experimental::filesystem的支持,但刚刚遇到了Unicode问题。我有点盲目地认为我可以在任何地方使用UTF-8字符串,但是失败了 - 当从std::experimental::filesystem::path构造char*到UTF-8编码的字符串时,不会发生转换(即使标题使用{{ 1}}和_To_wide函数在内部。我写了一个简单的测试示例:

_To_byte

但正如我之前所说,我只是盲目地认为UTF-8会起作用。看一下构造函数secion下的std::experimental::filesystem::path on cppreference.com,它实际上说明了:

  
      
  • 如果源字符类型为char,则源的编码为   假设是原生的窄编码(因此不需要转换   放在POSIX系统上)
  •   
  • 如果源字符类型为char16_t,   使用从UTF-16到本机文件系统编码的转换。
  •   
  • 如果源字符类型为char32_t,则从UTF-32转换为本机   使用文件系统编码。
  •   
  • 如果源字符类型是wchar_t,   假设输入是本机宽编码(因此没有转换   取代Windows)
  •   

我不确定如何解释第一行。首先,它只说明POSIX系统的一些东西(尽管我不明白什么是原生的窄编码,这是否意味着UTF-8也不适用于POSIX?)。其次,它没有说明Windows的任何内容,MSDN也对此保持沉默。那么,如何以跨平台的安全方式处理来自Unicode字符的#include <string> #include <experimental\filesystem> #define WIN32_LEAN_AND_MEAN #include <Windows.h> static inline std::string FromUtf16(const wchar_t* pUtf16String) { int nUtf16StringLength = static_cast<int>(wcslen(pUtf16String)); int nUtf8StringLength = ::WideCharToMultiByte(CP_UTF8, 0, pUtf16String, nUtf16StringLength, NULL, 0, NULL, NULL); std::string sUtf8String(nUtf8StringLength, '\0'); nUtf8StringLength = ::WideCharToMultiByte(CP_UTF8, 0, pUtf16String, nUtf16StringLength, const_cast<char *>(sUtf8String.c_str()), nUtf8StringLength, NULL, NULL); return sUtf8String; } static inline std::string FromUtf16(const std::wstring& sUtf16String) { return FromUtf16(sUtf16String.c_str()); } static inline std::wstring ToUtf16(const char* pUtf8String) { int nUtf8StringLength = static_cast<int>(strlen(pUtf8String)); int nUtf16StringLength = ::MultiByteToWideChar(CP_UTF8, 0, pUtf8String, nUtf8StringLength, NULL, NULL); std::wstring sUtf16String(nUtf16StringLength, '\0'); nUtf16StringLength = ::MultiByteToWideChar(CP_UTF8, 0, pUtf8String, nUtf8StringLength, const_cast<wchar_t*>(sUtf16String.c_str()), nUtf16StringLength); return sUtf16String; } static inline std::wstring ToUtf16(const std::string& sUtf8String) { return ToUtf16(sUtf8String.c_str()); } int main(int argc, char** argv) { std::string sTest(u8"Kaķis"); std::wstring sWideTest(ToUtf16(sTest)); wchar_t pWideTest[1024] = {}; char pByteTest[1024]; std::experimental::filesystem::path Path1(sTest), Path2(sWideTest); std::experimental::filesystem::v1::_To_wide(sTest.c_str(), pWideTest); bool bWideEqual = sWideTest == pWideTest; std::experimental::filesystem::v1::_To_byte(pWideTest, pByteTest); bool bUtf8Equal = sTest == pByteTest; bool bPathsEqual = Path1 == Path2; printf("wide equal: %d, utf-8 equal: %d, paths equal: %d\n", bWideEqual, bUtf8Equal, bPathsEqual); } 初始化属性?

1 个答案:

答案 0 :(得分:4)

&#34;狭窄&#34; ({1}}的(8位)编码取决于环境和主机OS。在许多POSIX系统上它可能是UTF-8,但也可能不是。如果您想使用UTF-8,则应通过std::filesystem::path::u8string()std::filesystem::u8path()

明确使用它