1

The following code only prints the file once:

#include <iostream>
#include <fstream>
using namespace std;

int main(int argc, const char *argv[])
{
    ifstream infile;
    infile.open("in", ios::binary);
    char c;

    while (infile.get(c))
    {
        cout << c;
    }

    infile.seekg(0, ios::beg);
    infile.clear();

    while (infile.get(c))
    {
            cout << c;
    }
    infile.close(); 
    return 0;
}

I assume it has something to do with the eof flag after running through the file, but I don't know how to fix that.

Cheers.

James Jenkinson
  • 1,563
  • 2
  • 16
  • 33
  • 3
    NO NO NO `while (!infile.eof())` Do NOT do this!! Use `while(infile >> c) { //do stuff with c }` instead. – Tony The Lion Feb 14 '13 at 18:49
  • 1
    @TonyTheLion I'm not sure you can use `operator>>` with a binary file, but your comment is still a step in the right direction. What I've used for reading binary files is `while( infile.read( &c, 1 ) { ... }` Also, James, the reason nothing is printed the second time if you use `infile.good()` is because some flag is being set by the first loop. Try calling `infile.clear()` before starting the second loop. – Praetorian Feb 14 '13 at 18:52
  • 1
    Possible indirect duplicate of http://stackoverflow.com/questions/1039667/why-does-stdfstream-set-the-eof-bit-the-way-it-does – Patrick B. Feb 14 '13 at 18:53
  • @TonyTheLion Or `while ( infile.get( c ) )`. Or even `int c = infile.get(); while ( c != EOF ) { ... ; c = infile.get(); }`. – James Kanze Feb 14 '13 at 19:32
  • @Praetorian Why shouldn't you be able to use the `>>` with a file opened in binary mode (which isn't necessarily a binary file). – James Kanze Feb 14 '13 at 19:34
  • @JamesKanze I didn't say you couldn't, just that I didn't know if you could. I've just never used it with a file in binary mode. – Praetorian Feb 14 '13 at 23:48
  • @Praetorian Interesting. Unless I'm using `>>` and `<<`, I usually won't bother with iostream. (I will occasionally use an `istream` for character input, just using `get`.) – James Kanze Feb 15 '13 at 08:42

1 Answers1

2

There are several problems with your code:

First, you don't check that infile.get() succeeds before using its results, ever. And you are using infile.good() to control one loop, and infile.eof() to control another: infile.eof() isn't useful until you know that the input has failed, and infile.good() is never really useful. Just use while ( infile.get( c ) ) for both loops.

Second, as you say, you never reset the "error" that caused you to finish the first loop. Once you've encountered the end of file (and infile.get( c ) has failed), you need to call infile.clear() before doing anything else.

Finally, of course, you fail to check whether you successfully opened the file, and whether the seekg succeeded. And you generally don't have to close an input file; it will be closed automatically when it goes out of scope. (On the other hand, you should either close or flush std::cout, and verify that it is still OK afterwards. Returning 0 when you've failed to write all of the data is a serious error in my book.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • (As far as I can tell) edited the code to the suggestions, it still doesn't print the second time around. – James Jenkinson Feb 14 '13 at 19:56
  • Also how exactly would you check whether seekg() 'worked'? By using tellg()? (If so it's returning -1, which I guess means seekg() isn't working, in which case, why?) – James Jenkinson Feb 14 '13 at 20:23
  • @JamesJenkinson The same way you tell if anything you do on an istream or an ostream worked: treat the stream as if it were a boolean; if it evaluates `true`, there have been no errors to date. – James Kanze Feb 15 '13 at 08:38
  • @JamesJenkinson You have to do the `clear()` _before_ the seek. A general rule with istream and ostream: errors are sticky. And trying to read beyond the end of file is an "error" (since the read didn't succeed). – James Kanze Feb 15 '13 at 08:40