如何使用unicode文件名打开std :: fstream(ofstream或ifstream)?
题
你不会想象像使用C ++标准库为Windows应用程序打开文件那样基本的东西很棘手......但它似乎是。在这里,我的意思是UTF-8,但我可以转换为UTF-16或其他任何东西,重点是从Unicode文件名获取一个ofstream实例。在我推出自己的解决方案之前,这里有一条首选路线吗?特别是跨平台的?
解决方案
C ++标准库不支持Unicode。 char
和 wchar_t
不需要是Unicode编码。
在Windows上, wchar_t
是UTF-16,但是标准库中没有直接支持UTF-8文件名( char
数据类型在Windows上不是Unicode)
使用MSVC(以及Microsoft STL),提供了一个文件流构造函数,它使用 const wchar_t *
文件名,允许您创建流:
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
但是,C ++ 11标准未指定此重载(它仅保证存在基于 char
的版本)。它也不存在于替代STL实现中,如GCC的用于MinGW的libstdc ++(-w64),从版本g ++ 4.8.x开始。
请注意,就像Windows上的 char
不是UTF8一样,在其他操作系统上 wchar_t
可能不是UTF16。总的来说,这不太可能是便携式的。给定 wchar_t
文件名打开流不是根据标准定义的,并且在 char
中指定文件名可能很困难,因为char使用的编码因OS而异。 ES。
其他提示
当前版本的Visual C ++ std :: basic_fstream有一个 open()
方法,根据 http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx 。
从C ++ 17开始,有一种跨平台的方法可以使用 std :: filesystem :: path 重载。在C ++ 20之前,您可以使用从UTF-8字符串创建路径。的std ::文件系统:: u8path 。例如:
std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
在C ++ 20之后,您可以通过将UTF-8传递给构造函数来创建路径: std :: filesystem :: path(u8&quot;&#12371;&#12435;&#12395;&# 12385;&#12399;&quot;)
(u8path将被弃用)。
使用 std :: wofstream
, std :: wifstream
和 std :: wfstream
。他们接受unicode文件名。文件名必须是 wstring
, wchar_t
的数组,或者它必须有 _T()
宏,或者前缀 L
在文本之前。
查看 Boost.Nowide :
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/cout.hpp>
using boost::nowide::ifstream;
using boost::nowide::cout;
// #include <fstream>
// #include <iostream>
// using std::ifstream;
// using std::cout;
#include <string>
int main() {
ifstream f("UTF-8 (e.g. ß).txt");
std::string line;
std::getline(f, line);
cout << "UTF-8 content: " << line;
}
如果您使用的是与 std :: ifstream
混合的Qt:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));