编者注:在Rust 1.0之前曾问过这个问题。从那时起,许多函数和类型都发生了变化,某些语言语义也发生了变化。问题中的代码不再有效,但答案中表达的想法可能是。
我正在尝试列出目录中的文件,并将文件名复制到我自己的Vec
。我已经尝试了几种解决方案,但它总是会遇到无法创建足够长的生存变量的问题。我不明白我的错误。
fn getList(action_dir_path : &str) -> Vec<&str> {
let v = fs::readdir(&Path::new(action_dir_path))
.unwrap()
.iter()
.map(|&x| x.filestem_str().unwrap())
.collect();
return v;
}
为什么编译器会抱怨“x”?我不关心x,我想在其中&str
,我认为&str
是静态的。
我试过这种方式,但是我得到了相同的结果,编译器抱怨“路径”的生存时间不够长。
fn getList2(action_dir_path : &str) -> Vec<&str> {
let paths = fs::readdir(&Path::new(action_dir_path)).unwrap();
let mut v : Vec<&str> = Vec::new();
for path in paths.iter(){
let aSlice = path.filestem_str().unwrap();
v.push(aSlice);
}
return v;
}
答案 0 :(得分:7)
支持Rust 1.0的代码的最直译是:
use std::{fs, path::Path, ffi::OsStr};
fn getList(action_dir_path: &str) -> Vec<&OsStr> {
let v = fs::read_dir(&Path::new(action_dir_path))
.unwrap()
.map(|x| x.unwrap().path().file_stem().unwrap())
.collect();
return v;
}
这会产生错误消息:
Rust 2015
error[E0597]: borrowed value does not live long enough
--> src/lib.rs:6:18
|
6 | .map(|x| x.unwrap().path().file_stem().unwrap())
| ^^^^^^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value does not live long enough
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 3:1...
--> src/lib.rs:3:1
|
3 | / fn getList(action_dir_path: &str) -> Vec<&OsStr> {
4 | | let v = fs::read_dir(&Path::new(action_dir_path))
5 | | .unwrap()
6 | | .map(|x| x.unwrap().path().file_stem().unwrap())
7 | | .collect();
8 | | return v;
9 | | }
| |_^
Rust 2018
error[E0515]: cannot return value referencing temporary value
--> src/lib.rs:6:18
|
6 | .map(|x| x.unwrap().path().file_stem().unwrap())
| -----------------^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
问题来自Path::file_stem
。这是签名:
pub fn file_stem(&self) -> Option<&OsStr>
这表示该方法将返回借用的OsStr
引用。 PathBuf
结构是字符串的所有者。当你离开这个方法时,没有任何地方可以拥有PathBuf
,所以它将被删除。这意味着对PathBuf
的任何引用都将不再有效。这是Rust阻止你引用不再分配的内存,不管是Rust!
您可以做的最简单的事情是返回Vec<String>
。 String
拥有其中的字符串,所以当我们离开函数时,我们不必担心它被释放:
fn get_list(action_dir_path: &str) -> Vec<String> {
fs::read_dir(action_dir_path)
.unwrap()
.map(|x| {
x.unwrap()
.path()
.file_stem()
.unwrap()
.to_str()
.unwrap()
.to_string()
})
.collect()
}
我还更新了风格(免费!)更像Rust:
snake_case
项目return
语句。Path
。然而,我并不是所有解缠的粉丝。我写这个函数是这样的:
use std::{ffi::OsString, fs, io, path::Path};
fn get_list(action_dir_path: impl AsRef<Path>) -> io::Result<Vec<OsString>> {
fs::read_dir(action_dir_path)?
.map(|entry| entry.map(|e| e.file_name()))
.collect()
}
fn main() {
println!("{:?}", get_list("/etc"));
}
除上述变更外:
Result
以向调用者传播错误。DirEntry
询问文件名。OsString
。答案 1 :(得分:0)
一个小相关点:
我认为&amp; str是静态的。
&'static str
是静态的,但这只是&str
中的一种。它可以有任何生命周期。