[英]Getting a boost::filesystem::path as an UTF-8 encoded std::string, on Windows
[英]UTF-8 support in Visual Studio 2017 std::experimental::filesystem::path
我很高興看到Visual Studio 2017中增加了對std::experimental::filesystem
的支持,但現在遇到了Unicode問題。 我有點盲目地假設我可以在任何地方使用UTF-8字符串,但是失敗了-在構造從char*
到UTF-8編碼字符串的std::experimental::filesystem::path
,不會進行任何轉換(即使標頭使用_To_wide
和_To_byte
內部有函數,我編寫了一個簡單的測試示例:
#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);
}
但是正如我之前所說,我只是盲目地認為UTF-8可以工作。 在構造器部分下查看cppreference.com上的std :: experimental :: filesystem :: path,它實際上指出:
- 如果源字符類型為char,則假定源的編碼為本機窄編碼(因此在POSIX系統上不進行轉換)
- 如果源字符類型為char16_t,則使用從UTF-16到本機文件系統編碼的轉換。
- 如果源字符類型為char32_t,則使用從UTF-32到本機文件系統編碼的轉換。
- 如果源字符類型為wchar_t,則假定輸入為本地寬編碼(因此Windows上不會進行任何轉換)
我不確定如何解釋第一行。 首先,它僅說明了與POSIX系統有關的內容(即使我不了解什么是本機窄編碼,這是否也意味着UTF-8也不能在POSIX上運行?)。 其次,它沒有聲明有關Windows的任何內容,MSDN也對此保持沉默。 那么,如何以跨平台安全的方式處理來自Unicode字符的std::experimental::filesystem::path
初始化?
filesystem::path
的“窄”(8位)編碼取決於環境和主機OS。 在許多POSIX系統上,它可能是UTF-8,但也可能不是。 如果要使用UTF-8,則應通過std::filesystem::path::u8string()
和std::filesystem::u8path()
顯式使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.