0

Possible Duplicate:
Reading from text file until EOF repeats last line
c++ EOF running one too many times?

I am writing a simple c++ code to read and write a binary file but I found that the ifstream will read the record twice. I don't know how this happens but I try to compile the code with mingw32 in windows and linux, the same case

ofstream outfile;
int data[5];
outfile.open("abc.out", ios::out | ios::trunc | ios::binary);
data[0] = data[1] = 1;
data[2] = data[3] = 2;
data[4] = -1;
cout << "ORIGINAL DATA:" << data[0] << " " << data[1] << " "  << data[2] << " "  << data[3] << " "  << data[4] << endl << endl;
outfile.write((char *)&data[0], 5*sizeof(int));
outfile.close();    


ifstream infile;
infile.open("abc.out", ios::in | ios::binary);
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
while (!infile.eof())
{
  infile.read((char *)&data[0], 5*sizeof(int));
  cout << data[0] << " " << data[1] << " "  << data[2] << " "  << data[3] << " "  << data[4] << endl;
}

Here is the output

ORIGINAL DATA:1 1 2 2 -1

1 1 2 2 -1

1 1 2 2 -1

Community
  • 1
  • 1
user1285419
  • 2,183
  • 7
  • 48
  • 70
  • `infile.eof()` returns true only *after* failing to read, so the loop runs one time too much. – Bo Persson Apr 08 '12 at 07:06
  • Thank Bo Persson, but I still don't understand how to fix that. Reading "Reading from text file until EOF repeats last line", I try the following code while (true) { ... if( infile.eof() ) break; } but still doesn't work – user1285419 Apr 08 '12 at 07:09
  • 1
    @user - You can test for eof, or check the return value of `read` (hint, hint!), before deciding to write to cout. – Bo Persson Apr 08 '12 at 07:13

3 Answers3

2

Don't ever use .eof() or .good() as loop condition. It almost always produces buggy code (as it does in this case).

The idiomatic pattern for reading data is C++ is this:

while (infile.read((char *)&data[0], 5*sizeof(int)))
{  
  cout << data[0] << " " << data[1] << " "  << data[2] << " "  
       << data[3] << " "  << data[4] << endl;
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
2

As @BoPersson already pointed out, the problem stems from using while (!infile.eof()), which is virtually always an error. Instead, you want to check the result of reading the data. A first approximation would look something like this:

// prefer 1-step initialization -- supply parameters to ctor.
ifstream infile("abc.out", ios::in | ios::binary); 

while (infile.read((char *)&data[0], 5*sizeof(int))
    cout << data[0] << " " 
         << data[1] << " "  
         << data[2] << " "  
         << data[3] << " "  
         << data[4] << endl;
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

Since a stream goes bad when a read fails and a bad stream can be seen as a false bool, and since read returns the stream istelf, you can do

while(infile.read((char *)&data[0], 5*sizeof(int)))
  cout << data[0] << " " << data[1] << " "  << data[2] << " "  << data[3] << " "  << data[4] << endl;

thus leaving the loop just on the read failure.

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63