Search code examples
filerustioseek

How can I get the current position in a `BufReader` for a file?


How do I get the current position of the cursor in an opened filestream in rust, after reading several lines?

For examples: Here I am moving the cursor 6 bytes from start. Read until 50 characters. After this I would like to get the current position of the cursor, and seek the cursor again from its position.

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

fn main() {

    let fafile: String = "temp.fa".to_string();
    let mut file = File::open(fafile).expect("Nope!");
    let seekto: u64 = 6;
    file.seek(SeekFrom::Start(seekto)); //open a file and seek 6 bytes
    let reader = BufReader::new(file);

    let mut text: String = "".to_string();

    //Stop reading after 50 characters
    for line in reader.lines(){
        let line = line.unwrap();
        text.push_str(&line);
        if text.len() > 50{ 
            break;
        }
    }

   //How do I get the current position of the cursor? and
  // Can I seek again to a new position without reopening the file? 
  //I have tried below but it doesnt work.

   //file.seek(SeekFrom::Current(6)); 

}

I have checked seek which offers to move the cursor from start, end and current but does not tell me the current position.


Solution

  • Regarding your first question, seek returns the new position after moving. So you can get the current position by seeking with an offset of 0 from the current:

    let current_pos = reader.seek (SeekFrom::Current (0)).expect ("Could not get current position!");
    

    (see also this question)

    Regarding the second question, you can no longer access the file variable once you've moved it into the BufReader, but you can call seek on the reader itself:

    reader.seek (SeekFrom::Current (6)).expect ("Seek failed!");
    

    As pointed out in the comments, this only works if you haven't moved the reader, so you also need to change your reading loop to borrow reader instead of moving it:

    for line in reader.by_ref().lines() {
        // ...
    }