I\'m trying to read some lines from a file, skipping the first few and printing the rest, but I keep getting errors about used value after move:
use std::fs:
As Lukas Kalbertodt says, use Read::by_ref.
This prevents lines
from consuming the BufReader
and instead it consumes a &mut BufReader
. The same logic applies to iterators.
Instead of implementing skip
yourself, you can use Iterator::take. This has to be driven to completion with a for loop though:
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");
}
Note that there's no reason to make the skip
variable mutable or even to pass in a reference. You can also take in AsRef<Path>
and then callers of skip_and_print_file
can just pass in a string literal.
In order to avoid the move, use the Read::by_ref() method. That way, you only borrow the BufReader
:
for (index, line) in buffer.by_ref().lines().enumerate() { ... }
// ^^^^^^^^^
// you can still use `buffer` here