使用 filesystem::path,如何以跨平台方式打开文件?

Posted

技术标签:

【中文标题】使用 filesystem::path,如何以跨平台方式打开文件?【英文标题】:Using a filesystem::path, how do you open a file in a cross-platform way? 【发布时间】:2016-06-30 13:20:33 【问题描述】:

假设您使用了新的std::filesystem(或std::experimental::filesystem)代码来查找文件。您有一个 path 变量,其中包含此变量的完整路径名。

你如何打开那个文件?

这听起来可能很愚蠢,但考虑一下显而易见的答案:

std::filesystem::path my_path = ...;
std::ifstream stream(my_path.c_str(), std::ios::binary);

这不是保证有效的。为什么?因为例如在 Windows 上,path::string_typestd::wstring。所以path::c_str 将返回一个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 版本以直接支持paths。

我在这里遗漏了什么吗?委员会是否添加了跨平台文件系统库而不添加跨平台方式来打开其中的文件?

【问题讨论】:

扩展名很可能会标准化Defect Report 2676。可能是上周发生的。 basic_ifstream<path::value_type> stream(my_path); 会起作用,还是我错过了什么?肯定不好看…… @chris: 不。basic_ifstream 的字符类型是指它读取/写入的 数据 的字符类型,而不是它所采用的路径。跨度> @NicolBolas,对,我的错。 【参考方案1】:

Bo Persson 指出这是standard library defect report 的主题。此缺陷已得到解决,C++17 将发布,要求在 path::value_type 不是 char 的实现中,除了通常的 const char* 版本之外,它们的文件流类型采用 const filesystem path::value_type*s。

【讨论】:

没有。虽然它可能会在 C++17 发布之前修复。 开业时间:2017-03-09 (open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2943)

以上是关于使用 filesystem::path,如何以跨平台方式打开文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::filesystem::path 获取绝对路径

boost::filesystem::path 中的“/”字符有啥用?

std::filesystem::path 的奇怪运算符/

检查 std::filesystem::path 是不是在目录中

如何以跨浏览器的方式使用 JavaScript 将 DOM 序列化为 XML 文本?

使用简单 Ls.cpp 的 C++ Boost 编译错误 - 未定义对 boost::filesystem::path::filename 的引用