25

I am trying to do a seek and re-read the data. but the code fails.

The code is

std::ifstream ifs (filename.c_str(), std::ifstream::in | std::ifstream::binary);

std::streampos pos = ifs.tellg();

std::cout <<" Current pos:  " << pos << std::endl;

// read the string
std::string str;
ifs >> str;

std::cout << "str: " << str << std::endl;
std::cout <<" Current pos:  " <<ifs.tellg() << std::endl;

// seek to the old position
ifs.seekg(pos);

std::cout <<" Current pos:  " <<ifs.tellg() << std::endl;

// re-read the string
std::string str2;
ifs >> str2;

std::cout << "str2: (" << str2.size() << ") " <<  str2 << std::endl;
std::cout <<" Current pos:  " <<ifs.tellg() << std::endl;

My input test file is

qwe

The output was

 Current pos:  0
str: qwe
 Current pos:  3
 Current pos:  0
str2: (0)
 Current pos:  -1

Can anyone tell me what's wrong?

veda
  • 6,416
  • 15
  • 58
  • 78
  • possible duplicate of [seekg() function fails](http://stackoverflow.com/questions/11264764/seekg-function-fails) โ€“ amo Sep 16 '14 at 23:00

2 Answers2

41

When ifs >> str; ends because the end of file is reached, it sets the eofbit.

Until C++11, seekg() could not seek away from the end of stream (note: yours actually does, since the output is Current pos: 0, but that's not exactly conformant: it should either fail to seek or it should clear the eofbit and seek).

Either way, to work around that, you can execute ifs.clear(); before ifs.seekg(pos);

Cubbi
  • 46,567
  • 13
  • 103
  • 169
  • 2
    even though the C++ standard (n3337 ยง27.7.2.3.41) says "Effects: Behaves as an unformatted input function (as described in 27.7.2.3, paragraph 1), except that the function first clears eofbit...", actually, we still need to call `clear()` manually, that's very weird. โ€“ Gavin Jun 12 '19 at 08:34
  • 1
    @Gavin I was observing a similar behavior. However, it turns out that when using `read` to read the number of bytes the file has, then no eof bit is set. And as soon as you request one more byte than the file contains, **both** the failbit and eofbit are set but only the eofbit [will be cleared](https://en.cppreference.com/w/cpp/io/basic_istream/seekg) by `seekg` since C++11. โ€“ mxmlnkn Jun 11 '21 at 22:18
6

It looks like in reading the characters it is hitting the EOF and marking that in the stream state. The stream state is not changed when doing the seekg() call and so the next read detectes that the EOF bit is set and returns without reading.

diverscuba23
  • 2,165
  • 18
  • 32