Question

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();
}
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top