How to restore istream's state?

P

Peng Yu

Hi,

Suppose, I have the following code and the requirement is written
along with the code. I'm wondering if there is a way to restore the
state of an istream.

int n, m;
std::ifstream file("file.txt");
file >> n;

//I want to restore the state of 'file' here.
file >> m;//so that m would get the same value as n.

Thanks,
Peng
 
D

Darío Griffo

Peng said:
Hi,

Suppose, I have the following code and the requirement is written
along with the code. I'm wondering if there is a way to restore the
state of an istream.

int n, m;
std::ifstream file("file.txt");
file >> n;

//I want to restore the state of 'file' here.
file >> m;//so that m would get the same value as n.

No standard function to do that, but:

int n, m,where;
std::ifstream file("file.txt");
where = file.tellg();
file >> n;
file.seekg(where);
file >> m;

should be enough for you
 
P

Peng Yu

No standard function to do that, but:

int n, m,where;
std::ifstream file("file.txt");
where = file.tellg();
file >> n;
file.seekg(where);
file >> m;

should be enough for you

This would miss all the error bits and maybe other internal states.
How to get all the internal states variables? Maybe I should keep a
record of them and then restore them completely?

Thanks,
Peng
 
P

Peng Yu

This would miss all the error bits and maybe other internal states.
How to get all the internal states variables? Maybe I should keep a
record of them and then restore them completely?

For example, the following code shows that other state variables are
also important.

#include <sstream>
#include <iostream>
#include <istream>

class istream_restorer {
public:
istream_restorer(std::istream &is);
void doit() const;
private:
mutable std::istream &_is;
mutable std::streampos _where;
};

istream_restorer::istream_restorer(std::istream &is) :
_is(is),_where(_is.tellg()) {
}

void istream_restorer::doit() const {
_is.seekg(_where);
}

int main() {
std::istringstream iss(
"10 9 8 7"
);

istream_restorer isr(iss);

std::string s;
if(getline(iss, s))
std::cout << s << std::endl;
else
std::cout << "Error" << std::endl;

isr.doit();
s = "";
if(getline(iss, s))
std::cout << s << std::endl;
else
std::cout << "Error" << std::endl; // would produce an error here.
}
 
J

James Kanze

Suppose, I have the following code and the requirement is
written along with the code. I'm wondering if there is a way
to restore the state of an istream.
int n, m;
std::ifstream file("file.txt");
file >> n;
//I want to restore the state of 'file' here.
file >> m;//so that m would get the same value as n.

It depends which state you're talking about. Although there's
no standard solution, it's usual to have a class which saves and
restores the formatting state (fmtflags, precision and fill).
There's also a function copyfmt() which copies everything but
the error status and the streambuf pointer; be careful with this
one, however, because it can change the exceptions mask, and
thus trigger an exception.

If you want to reread from the same place, istream::tellg() and
istream::seekg() are a possible solution (but be aware that they
don't work on all types of streams, and may not work on an
ifstream, depending on the file type). You can't, and normally
don't want to save and restore error state; if you're going back
in the file, after having (maybe) seen EOF, just use
ios::clear(). (If the first read succeeded, there was no error
before then.)

There is, IMHO, an error in the standard here. If eofbit is
set, but no other status bit, seekg() should logically clear it,
since the fact that you are at the end of file (but no operation
has actually failed yet) doesn't prevent you from seeking
(although it does mean that a read will fail), and after
seeking, you probably aren't at the end of file anymore. The
standard does allow seekg() to proceed if eofbit is set (unlike
the case with other functions), but doesn't have it resetting
this bit. As a general principle, I would suggest using clear()
before seeking.

Of course, if you really want to restore exactly the initial
state, the simplest solution is to just construct a new
instance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top