1

I'm trying to create a function that returns the position of a string within a file. This is my code:

use std::{
    fs::File,
    io::{BufRead, BufReader, Seek, SeekFrom},
};

fn find(log_file: &str, key: &str) -> Option<u64> {
    let log = File::open(log_file).unwrap();
    let mut reader = BufReader::new(log);
    for line in reader.lines() {
        let line = line.unwrap();
        if line.starts_with(&format!("{},", key)) {
            let bytes = line.as_bytes();
            let current_offset = reader.seek(SeekFrom::Current(0)).unwrap();
            return Some(current_offset - bytes.len() as u64);
        }
    }
    None
}

playground

When I attempt to compile I get:

error[E0382]: use of moved value: `reader`
  --> src/main.rs:13:34
   |
9  |     for line in reader.lines() {
   |                 ------ value moved here
...
13 |             let current_offset = reader.seek(SeekFrom::Current(0)).unwrap();
   |                                  ^^^^^^ value used here after move
   |
   = note: move occurs because `reader` has type `std::io::BufReader<std::fs::File>`, which does not implement the `Copy` trait

Is there any way I can make this work?

This question is not a duplicate of Cannot use moved BufReader after for loop with bufreader.lines() because using by_ref doesn't work either because then the compiler tells me that reader is borrowed twice mutably.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Thomas Maurin
  • 357
  • 4
  • 9

1 Answers1

1

I think you should use .read_line() here. This is more efficient than calling .lines()

use std::{
    fs::File,
    io::{BufRead, BufReader},
};

fn find(log_file: &str, key: &str) -> Option<u64> {
    let log = File::open(log_file).unwrap();
    let mut reader = BufReader::new(log);
    let mut line = String::new();
    let mut pos = 0;
    while let Ok(num) = reader.read_line(&mut line) {
        if num == 0 {
            break;
        }
        if line.starts_with(&format!("{},", key)) {
            return Some(pos);
        }
        pos += num as u64;
        line.clear();
    }
    None
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
rnbguy
  • 1,369
  • 1
  • 10
  • 28