I have a function (legacy) that reads the first few lines of a file to determine its type, then closes and reopens the file so it can re-read the entire file using the correct interpreter. The gist is:
void readFile(const char *filename) {
ifstream is(filename);
Filetype ft = determineFileType(is);
is.close();
is.open(filename);
parseFile(is, ft);
}
I needed a similar function that can work on an already-opened stream. I created a new function that takes an ostream &
instead of a char *filename
-- basically this:
void readFile(istream &is) {
std::ios::streampos pos = is.tellg();
Filetype ft = determineFileType(is);
is.seekg(pos);
parseFile(is, ft);
}
It seems to work when the istream
is actually a stringstream
or an fstream
but I wonder if I'm just getting lucky. I also did a small test on seekg
-ing std::cin
and it worked, which surprised me.
So my question: what kinds of streams are you allowed to use seekg
on? When will it fail? Spec references would be great -- I looked through and the stuff on seekg
, pubseekpos
, seekpos
, seekoff
weren't helpful at all.
I'd like to reimplement the original function in terms of the new (as below), but I just don't know if that's safe.
void readFile(const char *filename) {
ifstream is(filename);
readFile(is);
is.close();
}
The only real answer one can give is that it works where it works. In
the case of std::stringbuf
, it should work everywhere. In the case of
std::filebuf
, whether it works or not depends on the system; it will
generally work if the filebuf
is opened on an actual file, but will
usually fail (perhaps silently, if the system doesn't report an error)
for many other types of input: from a keyboard, or a named pipe, for
example.
A more robust solution would be to cache the initial input, and re-read it from the cache.
精彩评论