使用filesystem::path,如何以跨平台方式打开文件?
Using a filesystem::path, how do you open a file in a cross-platform way?
假设您使用了新的 std::filesystem
(或 std::experimental::filesystem
)代码来搜索文件。您有一个 path
变量,其中包含该变量的完整路径名。
你如何打开那个文件?
这听起来可能很傻,但考虑一下显而易见的答案:
std::filesystem::path my_path = ...;
std::ifstream stream(my_path.c_str(), std::ios::binary);
这不能保证工作。为什么?因为例如 Windows,path::string_type
是 std::wstring
。所以path::c_str
会return一个const wchar_t*
。 std::ifstream
只能 采用 const char*
类型的路径。
现在证明这段代码在 VS 中确实可以运行。为什么?因为Visual Studio有个library extension that does permit this to work。但这是非标准行为,因此不是 可移植的。例如,我不知道 Windows 上的 GCC 是否提供相同的功能。
你可以试试这个:
std::filesystem::path my_path = ...;
std::ifstream stream(my_path.string().c_str(), std::ios::binary);
只有Windows又把我们搞糊涂了。因为如果 my_path
恰好包含 Unicode 字符,那么现在您需要正确设置 Windows ANSI 语言环境。如果路径恰好包含来自同一 ANSI 区域设置中不能存在的多种语言的字符,即使这样也不一定能救你。
Boost Filesystem 其实也有类似的问题。但是他们扩展了他们的 iostreams 版本以直接支持 path
s。
我是不是漏掉了什么?委员会是否添加了跨平台文件系统库,但没有添加跨平台方式来 open 中的文件?
Bo Persson指出这是一个standard library defect report的主题。此缺陷已解决,C++17 将发布,要求实现 path::value_type
不是 char
的文件流类型除了通常的 [=13] 外还采用 const filesystem path::value_type*
s =] 版本。
假设您使用了新的 std::filesystem
(或 std::experimental::filesystem
)代码来搜索文件。您有一个 path
变量,其中包含该变量的完整路径名。
你如何打开那个文件?
这听起来可能很傻,但考虑一下显而易见的答案:
std::filesystem::path my_path = ...;
std::ifstream stream(my_path.c_str(), std::ios::binary);
这不能保证工作。为什么?因为例如 Windows,path::string_type
是 std::wstring
。所以path::c_str
会return一个const wchar_t*
。 std::ifstream
只能 采用 const char*
类型的路径。
现在证明这段代码在 VS 中确实可以运行。为什么?因为Visual Studio有个library extension that does permit this to work。但这是非标准行为,因此不是 可移植的。例如,我不知道 Windows 上的 GCC 是否提供相同的功能。
你可以试试这个:
std::filesystem::path my_path = ...;
std::ifstream stream(my_path.string().c_str(), std::ios::binary);
只有Windows又把我们搞糊涂了。因为如果 my_path
恰好包含 Unicode 字符,那么现在您需要正确设置 Windows ANSI 语言环境。如果路径恰好包含来自同一 ANSI 区域设置中不能存在的多种语言的字符,即使这样也不一定能救你。
Boost Filesystem 其实也有类似的问题。但是他们扩展了他们的 iostreams 版本以直接支持 path
s。
我是不是漏掉了什么?委员会是否添加了跨平台文件系统库,但没有添加跨平台方式来 open 中的文件?
Bo Persson指出这是一个standard library defect report的主题。此缺陷已解决,C++17 将发布,要求实现 path::value_type
不是 char
的文件流类型除了通常的 [=13] 外还采用 const filesystem path::value_type*
s =] 版本。