6

Given this code:

let any_offset: u64 = 42;
let mut file = File::open("/home/user/file").unwrap();
file.seek(SeekFrom::Start(any_offset));
// println!("{:?}", file.cursor_position()) 

How can I obtain the current cursor position?

Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
AndreyT
  • 1,389
  • 12
  • 25
  • 4
    inspecting the result of `seek`. See the [docs for seek](https://doc.rust-lang.org/std/io/trait.Seek.html#tymethod.seek), `seek` returns a `Result`, where the u64 is the new position – Paolo Falabella Jan 19 '16 at 14:40
  • @PaoloFalabella: Shouldn't that be an answer? – Matthieu M. Jan 19 '16 at 18:59
  • It turns out that if I need it value later, then I should store it somehow, and manually update after each `seek` ? In my opinion it's stupid. – AndreyT Jan 19 '16 at 22:05
  • Or as alternative way: wrap File struct to my own and add needed functionality (i.e. create Proxy with position() method). But why I should do that, if it is the responsibility of File? – AndreyT Jan 19 '16 at 22:11

2 Answers2

12

You should call Seek:seek with a relative offset of 0. This has no side effect and returns the information you are looking for.

Seek is implemented for a number of types, including:

  • impl Seek for File
  • impl<'_> Seek for &'_ File
  • impl<'_, S: Seek + ?Sized> Seek for &'_ mut S
  • impl<R: Seek> Seek for BufReader<R>
  • impl<S: Seek + ?Sized> Seek for Box<S>
  • impl<T> Seek for Cursor<T> where
  • impl<W: Write + Seek> Seek for BufWriter<W>

Using the Cursor class mentioned by Aaronepower might be more efficient though, since you could avoid having to make an extra system call.

Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
David Grayson
  • 79,096
  • 23
  • 144
  • 182
  • So for a stream implementing `Seek` but not providing direct cursor access, the only way is `stream.seek(SeekFrom::Current(0)).unwrap()`. That's...verbose. – Kyle Strand Jan 16 '19 at 01:46
  • 6
    ...actually, there's a deeper problem: this requires mutably borrowing the stream. – Kyle Strand Jan 16 '19 at 01:49
  • Careful, if you're using a `BufWriter` this has the side affect of flushing to disk, even if the offset is just `0` like in this case. This can have a serious performance impact. – Todd Sewell Oct 26 '21 at 20:04
3

According to the Seek trait API the new position is returned with the seek function. However you can also take the data of the File, and place it within a Vec, and then wrap the Vec in a Cursor which does contain a method which gets the current position.

Without Cursor

let any_offset: u64 = 42;
let mut file = File::open("/home/user/file").unwrap();
let new_position = file.seek(SeekFrom::Start(any_offset)).unwrap();
println!("{:?}", new_position);

With Cursor

use std::io::Cursor;

let any_offset: u64 = 42;
let mut file = File::open("/home/user/file").unwrap();
let contents = Vec::new();
file.read_to_end(&mut contents);
let mut cursor = Cursor::new(contents);
cursor.seek(SeekFrom::Start(any_offset));
println!("{:?}", cursor.position());
XAMPPRocky
  • 2,870
  • 3
  • 21
  • 43