9

After I read a line from a file using ifstream, is there a way to bring the stream back to the beginning of the line I just read, conditionally?

using namespace std;
//Some code here
ifstream ifs(filename);
string line;
while(ifs >> line)
{
   //Some code here related to the line I just read

   if(someCondition == true)
   {
    //Go back to the beginning of the line just read
   }
   //More code here
} 

So if someCondition is true, the next line read during the next while-loop iteration will be the same line I just read right now. Otherwise, the next while-loop iteration will use the following line in the file. If you need further clarification, please don't hesitate to ask. Thanks in advance!

UPDATE #1

So I tried the following:

while(ifs >> line)
{
   //Some code here related to the line I just read
   int place = ifs.tellg();
   if(someCondition == true)
   {
    //Go back to the beginning of the line just read
    ifs.seekg(place);
   }
   //More code here
}

But it doesn't read the same line again when the condition is true. Is an integer an acceptable type here?

UPDATE #2: The Solution

There was an error in my logic. Here is the corrected version that works as I want it to for any of those that are curious:

int place = 0;
while(ifs >> line)
{
   //Some code here related to the line I just read

   if(someCondition == true)
   {
    //Go back to the beginning of the line just read
    ifs.seekg(place);
   }
  place = ifs.tellg();
   //More code here
}

The call to tellg() was moved to the end because you need to seek to the beginning of the previously read line. The first time around I called tellg() and then called seekg() before the stream even changed, which is why it seemed like nothing changed (because it really hadn't). Thank you all for your contributions.

The Unknown Dev
  • 3,039
  • 4
  • 27
  • 39

2 Answers2

6

There is no direct way to say "get back to the start of the last line". However, you can get back to a position you kept by using std::istream::tellg(). That is, before reading a line you'd use tellg() and then seekg() to get back to the position.

However, calling the seek functions frequently is fairly expensive, i.e., I would look at removing the requirement to read lines again.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Thanks. Efficiency isn't my immediate concern, but I'll try to look into some other means of doing it later. Right now my main focus is just getting something that works. – The Unknown Dev Oct 15 '12 at 21:20
  • I need to read characters from a 40gb file in a function until I hit a characters (delimiter characters) that the function should not read. Is using peek() less expensive or tellg() seekg() to mark the previous character position, which I need to return to? I guess the most efficient would be to not use any of this and just return the extra read character. – Behrooz Karjoo Feb 08 '17 at 21:13
  • @BehroozKarjoo: using `peek()` is fairly cheap. Essentially it does `return this->gptr() != this->egptr()? *this->gptr(): this->underflow();` (it properly expands the `char` into an `int`, though). Assuming the stream is buffered this is a pointer conparison and a dereference. A `peek()` call does a lot more work. – Dietmar Kühl Feb 08 '17 at 22:09
4

Store fstream position in the file (look at documentation).

Read line.

If condition happens - go to stored position in the file.

You need this:

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112