问题描述
我有一个应用程序使用 utf-8 编码的宽字符串处理文件 I/O。
工作代码:
const wchar_t* wc = L"C:\Documents\TestPath\TestFile.txt";
std::wfstream wf(wc);
wf.imbue(std::locale(wf.getloc(),new std::codecvt_utf8<wchar_t,0x10ffff,std::consume_header>()));
return wf.is_open();
...
wf << L"測試文件夾" << L"\n";
但是,一旦在文件路径中引入了 unicode 字符,文件将无法正常打开。 IE。以下代码不起作用并返回false:
const wchar_t* wc = L"C:\Documents\測試文件夾\TestFile.txt";
std::wfstream wf(wc);
return wf.is_open();
我在这里做错了什么?似乎应该有一种简单的方法可以让 wfstream 使用 unicode 文件路径,但我已经在互联网上搜索了所有内容,但找不到。
谢谢
解决方法
感谢大家的帮助。
我发现了如何让代码使用一个不寻常的解决方案,这可能会对处于相同情况的其他人有所帮助:
- 使用 C 风格的 _wfopen 创建文件
FILE * fp = _wfopen(cpFullPath,L"w");
fclose(fp);
- 使用 ::GetShortPathW 函数获取新创建文件的 UTF8 路径的简短 ASCII 表示
wchar_t short_path[511] {} ;
::GetShortPathNameW( cpFullPath,short_path,511 ) ;
// cpFullPath is L"C:\\Desktop\\測試文件夾\\те \x81това \x8f папка\\file.txt"
// short_path becomes L"C:\\Desktop\\12BE~3\\81C2~6\\file.txt"
- 使用 wfstream 打开文件并为 UTF8 I/O 注入流
std::wfstream textFileStream;
textFileStream.open(short_path,ios::in | ios::out);
textFileStream.imbue(std::locale(textFileStream.getloc(),new std::codecvt_utf8<wchar_t,0x10ffff,std::consume_header>()));
,
您的字符串文字需要转义 \
个字符,例如:
const wchar_t* wc = L"C:\\Documents\\TestPath\\TestFile.txt";
const wchar_t* wc = L"C:\\Documents\\測試文件夾\\TestFile.txt";
否则,请改用原始字符串文字:
const wchar_t* wc = LR"(C:\Documents\TestPath\TestFile.txt)";
const wchar_t* wc = LR"(C:\Documents\測試文件夾\TestFile.txt)";
话虽如此,请仔细检查用于保存 cpp 文件的字符集是否与编译器用于解析文件的字符集匹配,否则像 測試文件夾
这样的非 ASCII 字符将无法在字符串文字中正确工作。
否则,请改用 Unicode 转义序列:
const wchar_t* wc = L"C:\\Documents\\\u6e2c\u8a66\u6587\u4ef6\u593e\\TestFile.txt";