在for循环中从DirEntry获取文件信息

时间:2015-07-28 02:54:14

标签: rust lifetime

我是Rust的新手。我正在尝试构建一个JSON对象,其中键是文件名,值是文件内容。

到目前为止,我有:

use std::fs;
use std::io;
use std::env;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

fn main() {
    make_json();
}

fn make_json() -> io::Result<()> {
    let mut modules = HashMap::new();
    let mut dir = env::current_dir().unwrap();
    let mut read_dir = fs::read_dir(dir);

    for entry in try!(read_dir) {
        let entry = try!(entry);
        let file_name = entry.path().file_name().unwrap().to_string_lossy();
        modules.insert(file_name, "");
    }

    Ok(())
}

当我去编译它时,我得到了

src/main.rs:19:25: 19:37 error: borrowed value does not live long enough
src/main.rs:19         let file_name = entry.path().file_name().unwrap().to_string_lossy();
                                       ^~~~~~~~~~~~
note: in expansion of for loop expansion
src/main.rs:17:5: 21:6 note: expansion site
src/main.rs:13:38: 23:2 note: reference must be valid for the block suffix following statement 0 at 13:37...
src/main.rs:13     let mut modules = HashMap::new();
src/main.rs:14     let mut dir = env::current_dir().unwrap();
src/main.rs:15     let mut read_dir = fs::read_dir(dir);
src/main.rs:16 
src/main.rs:17     for entry in try!(read_dir) {
src/main.rs:18         let entry = try!(entry);
               ...
src/main.rs:19:9: 19:77 note: ...but borrowed value is only valid for the statement at 19:8
src/main.rs:19         let file_name = entry.path().file_name().unwrap().to_string_lossy();
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:19:9: 19:77 help: consider using a `let` binding to increase its lifetime
src/main.rs:19         let file_name = entry.path().file_name().unwrap().to_string_lossy();
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

我明白这个错误告诉我的是什么; entry是在for循环的范围内定义的,因此如果我将它存储到HashMap,它将不再是有效的内存,因为内存中的位置已经被释放。我知道了。

我没有得到的是,如何在不使用某种闭包的情况下访问DirEntry中的read_dir,因为我需要在我检索它们的任何闭包之外的信息。

我遇到的一切都无法帮助我。

1 个答案:

答案 0 :(得分:2)

DirEntry.path()返回PathBuf,即'static(即它不包含非静态引用,并且是完全独立的对象)。 是问题所在。

PathBuf.file_name()返回Option<&OsStr>,对该对象的引用,以及OsStr.to_string_lossy() returns Cow<str>。最后请注意,不是 'static;随着生命周期的恢复,这是fn to_string_lossy<'a>(&'a self) -> Cow<'a, str>。这是为了提高效率,因为如果路径是合法的UTF-8,则无需创建全新的字符串(String),它可以将其保留为字符串切片(&str)。 (因为Cow<'a, str>就是这样的:填充了泛型的变体是Owned(String)Borrowed(&'a str)。)

您需要在此位置将Cow<str>变为String。这是通过into_owned method of Cow<T>完成的。

这一行代码就这样成了:

let file_name = entry.path().file_name().unwrap().to_string_lossy().into_owned();