使用bufreader.lines()的for循环后无法再使用已移动的BufReader。

12

我正在尝试从文件中读取一些行,跳过前几行并打印其余部分,但我不断收到有关move后使用值的错误:

use std::fs::File;
use std::io::{self, BufRead, BufReader, Read};
use std::path::Path;

fn skip_and_print_file(skip: &usize, path: &Path) {
    let mut skip: usize = *skip;

    if let Ok(file) = File::open(path) {
        let mut buffer = BufReader::new(file);
        for (index, line) in buffer.lines().enumerate() {
            if index >= skip {
                break;
            }
        }
        print_to_stdout(&mut buffer);
    }
}

fn print_to_stdout(mut input: &mut Read) {
    let mut stdout = io::stdout();
    io::copy(&mut input, &mut stdout);
}

fn main() {}

我遇到的错误如下:

error[E0382]: use of moved value: `buffer`
  --> src/main.rs:15:30
   |
10 |         for (index, line) in buffer.lines().enumerate() {
   |                              ------ value moved here
...
15 |         print_to_stdout(&mut buffer);
   |                              ^^^^^^ value used here after move
   |
   = note: move occurs because `buffer` has type `std::io::BufReader<std::fs::File>`, which does not implement the `Copy` trait
2个回答

15
为了避免移动(move),使用Read::by_ref() 方法。这样,您只会borrow BufReader
for (index, line) in buffer.by_ref().lines().enumerate() { ... }
//                         ^^^^^^^^^
// you can still use `buffer` here

11

Lukas Kalbertodt所说,使用Read::by_ref

这可以防止lines消耗BufReader,而是消耗一个&mut BufReader。相同的逻辑也适用于迭代器

你可以使用Iterator::take来避免自己实现skip。但是,需要通过for循环驱动它完成:

use std::{
    fs::File,
    io::{self, BufRead, BufReader, Read},
    path::Path,
};

fn skip_and_print_file(skip: usize, path: impl AsRef<Path>) {
    if let Ok(file) = File::open(path) {
        let mut buffer = BufReader::new(file);

        for _ in buffer.by_ref().lines().take(skip) {}
        // Or: buffer.by_ref().lines().take(skip).for_each(drop);

        print_to_stdout(buffer);
    }
}

fn print_to_stdout(mut input: impl Read) {
    let mut stdout = io::stdout();
    io::copy(&mut input, &mut stdout).expect("Unable to copy");
}

fn main() {
    skip_and_print_file(2, "/etc/hosts");
}

请注意,没有理由使skip变量可变,甚至不需要传递引用。您还可以接受AsRef<Path>,然后调用skip_and_print_file的调用者只需传递字符串文字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接