使用std::filesystem::path在分隔符类型之间进行转换



我正在编写的代码涉及从一个路径加载文件,该路径由给定的"基本"路径和从另一个文件加载的次要相对路径串联而成。例如(在我遇到问题的地方),基本路径是"assets/models/",次要路径是"maps\map.png"。这两个字符串的直接连接给出了"assets/models/maps\map.png"。当在POSIX系统上运行时,无法加载。到目前为止,我一直在通过将反斜杠替换为的正斜杠来解决这个问题

std::replace( path.begin(), path.end(), '\', '/' );

但我想用C++17的CCD_ 2来代替。

std::filesystem::path::make_preferred()的描述建议它应该取代分离器:

"将路径的通用格式视图中的所有目录分隔符转换为首选目录分隔符。例如,在Windows上,\是首选分隔符,路径foo/bar将转换为foo\bar">

然而,当在代码中实现时,它不会转换任何内容。我还验证了std::filesystem::path::preferred_separator是否符合预期-"/"。

我是不是误解了make_preferred()的目的?还是我只是用错了?

下面是一个不起作用的代码的精简版本(这不是实现的代码,但离它足够近):

const char * loadedPath = "maps\map.png"
std::string loadedPathStr = std::string( loadedPath );
auto wPath = std::filesystem::path( loadedPathStr );
wPath = wPath.make_preferred();
basePath = std::filesystem::path( "./a/b/" );
auto totalPath = basePath / wPath;
auto wStr = totalPath.generic_string();
std::cout << wStr << std::endl;

这会输出"./a/b/maps\\map.png">

在调试实现的代码时,看起来wPath被优化了;没有办法检查它。

奇怪的是,当我编译并运行这个独立的测试程序时,它能像预期的那样工作:

int main(){
assert( std::filesystem::path::preferred_separator == '/' );            
const char * cPath = "maps\map.png";
std::string path = std::string( cPath );
auto wPath = std::filesystem::path( path );
wPath = wPath.make_preferred();
std::string wStr = wPath.generic_string();
std::cout << wStr << std::endl;
}

这会输出"maps/map.png"。我无法阅读。这也会输出不正确的值。

有人知道这里发生了什么吗?

编辑:尝试使用clang进行编译(之前使用gcc),它按预期工作(转换了分隔符)忽略这一点,在重新编译时犯了一个错误。

我在Linux上运行这个,路径是存在的。

我是否误解了make_preferred()的用途?

不完全是,但微妙地是。目录分隔符(通用格式)是首选分隔符,也可以是后备分隔符:/。在首选分隔符为/(例如POSIX)的系统上,目录分隔符仅为/。在这样的系统上,make_preferred不会修改路径,这解释了为什么它会被完全优化。

用正斜杠替换反斜杠的最简单方法是std::replace。但是,请注意,在POSIX中,反斜杠是文件名中的有效字符,因此这种转换可能会中断使用它的文件名的使用

如果您想用filesystem编写跨平台代码,您应该尽量使用通用格式。所有其他格式的文件系统字符串的行为都取决于实现。

一个允许替代目录分隔符的实现将把它们当作目录分隔符。但是,其他完全有效的、不识别这些分隔符的实现将不会识别它们。"/"始终是目录分隔符;"\"是否是分隔符取决于实现。

make_preferred从实现的路径格式转换为通用格式。因此,它的行为依赖于实现。

处理非通用格式的主要原因是从本机操作系统API获取路径字符串。这样的路径字符串可能是实现的格式,因此path需要能够识别它们并使用它们。对于程序中内置的字符串文字,您应该始终选择通用格式(除非您的应用程序是特定于操作系统的,或者您根据代码使用的操作系统选择不同的字符串)。

最新更新