【发布时间】:2019-02-04 23:50:02
【问题描述】:
我正在编写涉及从路径加载文件的代码,该路径构造为从另一个文件加载的给定“基本”路径和辅助相对路径的串联。例如(在我遇到问题的地方),基本路径是“assets/models/”,辅助路径是“maps\map.png”。 这两个字符串的直接连接给出了“assets/models/maps\map.png”。在 POSIX 系统上运行时,无法加载。到目前为止,我一直在通过将反斜杠替换为正斜杠来解决这个问题
std::replace( path.begin(), path.end(), '\\', '/' );
但我想使用 C++17 的 std::filesystem::path 来代替。
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 上运行这个,路径存在。
【问题讨论】:
-
您使用的是 POSIX 平台还是 Windows?如果是 POSIX,在
assets子目录models中有一个名为maps\map.png的文件吗? -
你的工具链是什么?
-
请以 MCVE 形式提供非工作代码,例如 this。
-
问题可能是:在Windows上
\和/都是路径分隔符,而\是首选。在 POSIX 上,/是路径分隔符,而\不是路径分隔符,因此 make_preferred 不会转换\(它只是一个有效的普通文件名字符)。 -
顺便说一句,
make_preferred和generic_string基本上都做同样的事情,所以你不应该同时使用它们。make_preferred用于当您希望路径的内部存储字符串使用通用分隔符时。generic_string用于当您想要通用格式的路径字符串的 副本 时。