【问题标题】:Collect file names into `Vec<str>`将文件名收集到 `Vec<str>`
【发布时间】:2021-03-11 06:13:58
【问题描述】:

如何将目录中的文件名收集到 Vec&lt;&amp;str&gt; 之类的东西中:

let paths = fs::read_dir("...")
    .unwrap()
    .filter_map(|e| e.ok())
    .map(|e| e.path().to_str());

另外,如果文件夹不存在,如何让它返回一个空列表?

【问题讨论】:

  • match 在您的read_dir 电话上?这是unwrap() 假设一切正常的地方,但可能不是。

标签: rust


【解决方案1】:

fs::read_dir 返回一个遍历Result&lt;DirEntry&gt; 的迭代器,它公开了一个DirEntry::path 方法。此方法返回一个PathBuf,它拥有包含文件名的缓冲区。

在您的原始示例中,您尝试将这些转换为 &amp;str - 有两个问题:

  1. path() 返回一个 PathBuf,您可以从中获取引用(通过 to_str()),但您没有将 PathBuf 存储在任何地方,因此编译失败并出现此错误:
error[E0515]: cannot return value referencing temporary value
 --> src/main.rs:7:18
  |
7 |         .map(|e| e.path().to_str());
  |                  --------^^^^^^^^^
  |                  |
  |                  returns a value referencing data owned by the current function
  |                  temporary value created here
  1. to_str() 返回 Option&lt;str&gt; - 如果路径包含任何非 UTF8 字符,则返回 None。你最终会得到一个包含Option&lt;&amp;str&gt;Vec

我建议将它们收集到Vec&lt;PathBuf&gt; 中,就像这样简单:

    let paths = fs::read_dir("...")
        .unwrap()
        .filter_map(|e| e.ok())
        .map(|e| e.path())
        .collect::<Vec<_>>();

如果你真的需要它们作为字符串,你可以使用:

    let paths = fs::read_dir("...")
        .unwrap()
        .filter_map(|e| e.ok())
        .map(|e| e.path().to_string_lossy().into_owned())
        .collect::<Vec<_>>();

to_string_lossy() 会将路径转换为字符串,用替换字符替换任何非 utf8 字符。它返回一个Cow&lt;&amp;str&gt; - 它实际上可能拥有也可能不拥有该字符串。为了确保返回一个拥有的字符串,我们调用into_owned()

最后,如果文件夹不存在,要让它返回一个空列表,你可以使用这样的东西:

    let paths : Vec<PathBuf> = match fs::read_dir("/tmsp") {
    
        Err(e) if e.kind() == ErrorKind::NotFound => Vec::new(),
        
        Err(e) => panic!("Unexpected Error! {:?}", e),
        
        Ok(entries) => entries.filter_map(|e| e.ok())
            .map(|e| e.path())
            .collect()
            

    };

如果出现NotFound 以外的任何错误,上述示例会出现恐慌 - 实际上,您可能会更优雅地处理这种情况。

【讨论】:

  • 谢谢!我必须将.collect() 添加到最后一个表达式才能获得Vec&lt;String&gt;
  • @vasily 糟糕,完全忘记了这一点!我已将其添加到答案中
  • @vasily 请注意,将PathBuf 转换为String 是有损操作。通常,生成的字符串不能用于再次定位文件,因此它仅在非常有限的情况下有用。如this answer中所述,您更有可能想要Vec&lt;PathBuf&gt;
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-06
  • 2021-11-30
  • 2016-06-08
相关资源
最近更新 更多