我试图弄清楚如何从我当前所在的行继续遍历文件,而不必从头开始。我正在使用BufReader
完成逐行迭代。这是我要执行的操作的一个示例:
use std::{
fs::File,
io::{self, BufRead, BufReader},
};
fn main() -> io::Result<()> {
let chapter = "Chapter 1";
let sentence = "Sentence 1";
let file = File::open("document.txt")?;
let reader = BufReader::new(file);
for line in reader.lines() {
if chapter == line.unwrap() {
for line in reader.lines() {
if sentence == line.unwrap() {
println!("Found the reference!");
}
}
}
}
Ok(())
}
由于错误,我无法像这样迭代:error[E0382]: use of moved value: `reader`
--> src/main.rs:15:25
|
11 | let reader = BufReader::new(file);
| ------ move occurs because `reader` has type `std::io::BufReader<std::fs::File>`, which does not implement the `Copy` trait
12 |
13 | for line in reader.lines() {
| ------- `reader` moved due to this method call
14 | if chapter == line.unwrap() {
15 | for line in reader.lines() {
| ^^^^^^ value moved here, in previous iteration of loop
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `reader`
有没有办法使用相同的BufReader
继续进行行迭代?
最佳答案
我认为在所有情况下都必须对迭代进行解糖,因为与内置for
所允许的相比,您需要更多的控制权。我在这里看到两种可能性:
一种,只需将糖简化为while let
并在两个循环中使用相同的迭代器:
while let Some(line) = lines.next() {
if chapter == line.unwrap() {
while let Some(line) = lines.next() {
if sentence == line.unwrap() {
println!("Found the reference!");
}
}
}
}
这意味着“内部”循环将从“外部”循环停止的地方开始,但是“外部”循环将从“内部”停止的地方继续。如果这是不希望的,则可以使用
Itertools::tee
“ fork ”迭代器,但是我希望这需要将迭代器装箱,因为您要堆叠Tee
。这意味着要累积一堆动态调度的迭代器。tee
还要求Item
是可克隆的(另一项费用),这意味着您必须在迭代之前拆开值:let mut lines: Box<dyn Iterator<Item=_>> = Box::new(BufReader::new(file).lines().map(|l| l.unwrap()));
while let Some(line) = lines.next() {
let (a, sub) = lines.tee();
lines = Box::new(a);
if chapter == line {
for line in sub {
if sentence == line {
println!("Found the reference!");
}
}
}
}
关于file - 继续从文件中的当前行进行迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64852996/