【问题标题】:Convert string to portable filename with <filesystem> or Boost.Filesystem使用 <filesystem> 或 Boost.Filesystem 将字符串转换为可移植文件名
【发布时间】:2021-02-22 00:53:08
【问题描述】:

有没有一种简单的方法,使用&lt;filesystem&gt; 或&lt;boost/filesystem.hpp&gt; 将可能由std::vector&lt;char&gt; 表示的字节序列转换为可移植的文件名字符串,以便可以将结果转换回输入序列?


例如,如果平台允许文件名由 [a,f] 和 [0,9] 范围内的字符组成。适合上述约束的转换函数可能是简单地将每个字符输出为两位数十六进制等效值的转换函数,因此 {'a', 'b'} 将变为 "6768" 为 'a' -> 97 -> 0x67,和 'b' -> 98 -> 0x68。

【问题讨论】:

  • 我不太明白你在这里要求什么。第一段看起来很清楚(从输入字符串构建一个path,然后调用path::generic_u8string),但第二段是在讨论一种不能跨不同文件系统移植的字节编码方案。这个答案不适合那个。
  • @NicolBolas 澄清一下,考虑一个输入字节序列为“/a/b”的示例,现在从该路径构造的std::path 实例将在目录'a'。现在我们已经丢失了足够的信息来从文件名中恢复“/a/b”。如果您要将问题约束应用于输入序列“/a/b”,则生成的文件(带有某个名称)的名称将允许我们 1)取回原始序列,以及 2)导致文件名是它自己的,而不是另一个目录中的文件。
  • 好的,所以问题是您并不真正了解filesystem::path 中发生了什么。就像,你所说的关于 path 包含的内容都是错误的。

标签: c++ filenames c++20 boost-filesystem


【解决方案1】:

使用filesystem::path 非常简单。第一步是从字符序列构造一个path 对象。有两个可用的迭代器构造函数,以及将 C++ 的任何字符类型用于编码目的的构造函数。

那么,就call generic_u8string on that path object;您将获得一个 std::u8string(在 C++20 中;在 C++17 中,您将获得一个 std::string),其中包含以平台中立的通用格式格式化的路径。该字符串稍后也可用于重构 path 对象。

现在,实际上不允许从特定于平台的格式通过path 完全往返返回特定于平台的格式。您可以获得路径的本机字符串版本(path::u8string 返回此),但不能保证字节对字节相同的字符串。可以保证这两个字符串将标识相同的文件系统资源。因此,如果存在差异,那么它们并不重要。

【讨论】:

  • 所以从输入字符串构造路径仍然不会导致路径对象,这样 path::filename() 本身就可以用来重构整个输入字符串。例如。 wandbox.org/permlink/Y62R3zghdAp5rk9z 将在目录“b”中生成一个名为“a”的文件。请注意,问题是寻求一种将序列转换为文件名而不是路径的方法。
  • @Curious:如果path::filename 包含path 对象中包含的所有信息……那有什么意义呢?您能解释一下在这种情况下“文件名”是什么意思吗?也就是说,鉴于您在前面的“/a/b”评论中的示例,您认为该字符串的哪个部分是它的“文件名”?当您说“文件名”时,fs::path 将其定义为一件事,但我认为您的意思是不同的。所以只要遵循fs::path 的命名法就可以了。
  • 文件系统 API 通常具有您所指出的目录和文件的概念。在这种情况下,std::path 对象两者兼有。在 c++ stdlib 命名法中,目录组件是父路径,文件名是文件。我要的只是一种将字节序列转换为文件名的方法,以便可以反转转换(因此在示例中“/a/b”到某些x,然后返回到“/a /b") 并且没有输出 1) 通过文件系统 API 与目录合并或 2) 开头是无效的文件名。
  • @Curious:这并没有解决我的问题。你说“对一个文件名”,然后你说“对一些x”。它是哪一个?您是否希望它成为某种定义上被视为“文件名”的东西,或者您是否希望它只是任何东西,只要它不“与文件系统 API 与目录混为一谈”?最后一点是什么意思呢?您是说您想以一种可以将其解码回路径名的方式对路径名进行编码,但是文件系统 API 不会将编码版本视为路径名?因为 BASE64 可以做到这一点。
  • 通过文件系统 API 与目录合并 -- 例如。如果 f("xyz") 产生“/a/b/”,那么f 对我的用例无效,因为“/a/b/”代表一个目录。但是 Base32 听起来很有希望! (Base64 包含一个正斜杠,它不起作用)。谢谢!
猜你喜欢
  • 2011-01-14
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 2019-01-31
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2019-02-15
相关资源
最近更新 更多