编者注:此代码示例来自1.0之前的Rust版本,并且在语法上不是有效的Rust 1.0代码.此代码的更新版本会产生不同的错误,但答案仍包含有价值的信息.
我已经实现了以下方法来返回二维数据结构中的文件中的单词:
fn read_terms() -> Vec<Vec<String>> {
let path = Path::new("terms.txt");
let mut file = BufferedReader::new(File::open(&path));
return file.lines().map(|x| x.unwrap().as_slice().words().map(|x| x.to_string()).collect()).collect();
}
Run Code Online (Sandbox Code Playgroud)
这是Rust中正确的,惯用的和有效的方式吗?我想知道是否collect()需要经常调用,是否有必要调用to_string()这里来分配内存.也许返回类型应该以不同的方式定义,以便更具惯用性和效率?
小智 7
从文本文件中获取单词的方式更短,更易读.
use std::io::{BufRead, BufReader};
use std::fs::File;
let reader = BufReader::new(File::open("file.txt").expect("Cannot open file.txt"));
for line in reader.lines() {
for word in line.unwrap().split_whitespace() {
println!("word '{}'", word);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将整个文件作为单个读取String,然后构建指向内部单词的引用结构:
use std::io::{self, Read};
use std::fs::File;
fn filename_to_string(s: &str) -> io::Result<String> {
let mut file = File::open(s)?;
let mut s = String::new();
file.read_to_string(&mut s)?;
Ok(s)
}
fn words_by_line<'a>(s: &'a str) -> Vec<Vec<&'a str>> {
s.lines().map(|line| {
line.split_whitespace().collect()
}).collect()
}
fn example_use() {
let whole_file = filename_to_string("terms.txt").unwrap();
let wbyl = words_by_line(&whole_file);
println!("{:?}", wbyl)
}
Run Code Online (Sandbox Code Playgroud)
这将以较少的开销读取文件,因为它可以将其插入单个缓冲区,而读取行则BufReader意味着需要大量复制和分配,首先进入缓冲区内部BufReader,然后进入新分配String的每一行,然后进入String为每个单词新分配.它也将使用更少的内存,因为单个大型String和引用的向量比许多个体更紧凑String.
缺点是你不能直接返回引用的结构,因为它不能活过堆栈框架而保持单个大String.在example_use上面,我们必须将大号String放入一个let以便调用words_by_line.可以使用不安全的代码并String在私有结构中包装和引用来解决这个问题,但这要复杂得多.
| 归档时间: |
|
| 查看次数: |
3881 次 |
| 最近记录: |