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

时间:2019-02-04 14:57:45

标签: c++ c++17

我正在处理涉及从路径加载文件的代码,该路径构造为从另一个文件加载的给定“基本”路径和辅助相对路径的连接。例如(在我遇到问题的地方),基本路径是“ 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上运行它,并且路径存在。

2 个答案:

答案 0 :(得分:3)

  

我误解了make_preferred()的目的吗?

不完全是,但巧妙地是。目录分隔符(通用格式)是首选分隔符,还是后备分隔符:/。在首选分隔符为/(例如POSIX)的系统上,目录分隔符仅为/。在这样的系统上,make_preferred不会修改路径,这说明了为什么会对其进行完全优化。

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

答案 1 :(得分:1)

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

允许替代目录分隔符的实现会将其视为目录分隔符。但是其他无法识别分隔符的完全有效的实现将无法识别它们。 “ /”始终是目录分隔符; “ \”是否为分隔符取决于实现。

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

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