我正在其涉及从其被构造为给定的“碱”路径的级联和一个次级相对路径,从另一个文件中加载的路径加载文件的代码。例如(并在我遇到的一个问题),基本路径是“资产/模型/”,和次级路径是“地图\ map.png”。这两个字符串的直拼接赋予“资产/模型/图\ map.png”。当在POSIX系统上运行此加载失败。到现在为止我已经被刚刚更换的反斜杠被用斜杠整理了这一点
std::replace( path.begin(), path.end(), '\\', '/' );
但我想用C ++ 17的std::filesystem::path
要做到这一点,而不是。
std::filesystem::path::make_preferred()
的描述表明,它应更换分离器:
“在路径中的优选目录分隔符的通用格式的视图中的所有目录分隔符转换。例如,在Windows中,其中\是优选的分离器,路径富/棒将被转换为foo \栏”
当在代码中实现的,但是,它不转换任何东西。我也验证了的std ::文件系统::路径:: 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;
}
这个输出“地图/ map.png”。 我看不懂。这也输出了不正确的值。
任何人都知道什么是怎么回事呢?
编辑: 试图与铛(前使用gcc)编译和它按预期工作(分离器被转换)。 忽视这一点,在重新编译犯了一个错误。
我在Linux上运行这一点,路径存在。
我误解
make_preferred()
的目的是什么?
不完全是,但微妙的是。目录分隔符(在通用格式)或者是优选的隔板,或回退分离器:/
。上的系统中优选的隔板是/
(例如POSIX),目录分隔符是唯一/
。在这样的系统make_preferred
不修改的路径,这可以解释为什么它会被完全优化掉。
更换反斜杠正斜杠最简单的方法是std::replace
。但是,请注意,反斜杠是在POSIX文件名有效字符,所以这种转换可能会破坏使用使用它的文件名。
如果你想要写有filesystem
跨平台的代码,你应该尽量坚持使用通用格式。的文件系统串的所有其他格式的行为是依赖于实现的。
允许备选目录分隔符将把它们作为目录分隔符的实现。但是其他的,完全有效的,实现不认识那些分离将无法识别它们。 “/”始终是一个目录分隔符;无论是“\”是一个分离器或不依赖于实现。
make_preferred
从实现的路径格式转换为通用格式。因此,它的行为是依赖于实现。
后面在处理非通用格式的主要原因是当你从本地OS API获取路径字符串。这样的路径字符串将可能在执行的格式,所以path
需要能够识别它们,并与他们合作。对于字符串文字内置到你的程序,你应该总是喜欢通用格式(除非你的应用程序和具体的操作系统,或者你是根据你的代码正在使用的操作系统上选择不同的字符串)。