1

I am studying binary file of C++ nowadays. I made a example code for it, but it does not work well.

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

int main() {
    ofstream writeFile;
    ifstream readFile;
    int temp = 1;

    writeFile.open("file.dat", ios::binary);

    for (int i = 5; i <= 10 ; i++) // range 5 to 10
        writeFile.write((char*)(&i), sizeof(i));

    writeFile.close();

    readFile.open("file.dat", ios::binary);
    readFile.seekg(0);
    while (!readFile.eof()) {
        readFile.read((char*)(&temp), sizeof(temp));
        cout << "temp: " << temp << endl;
        readFile >> ws;
    }
    readFile.close();

    system("pause");
    return 0;
}

Here is the result:

temp: 5
temp: 6
temp: 7
temp: 8
temp: 167772160
temp: 167772160

When I change the range not to include 9 (for example, 5 to 8), it works well. Also, When I make the same code with double type, it works well. So I think the integer 9 is problem. Can you tell me why?

πάντα ῥεῖ
  • 83,259
  • 13
  • 96
  • 175
Younghoon Jeong
  • 475
  • 4
  • 6

2 Answers2

4

readFile >> ws; discards white space, which is non-sense for a binary stream. In this case, the character value 9 (which is '\t') is skipped, corrupting your stream. Simply remove that line.

The second problem is you are not checking the state of the stream between reading and displaying the value. EOF is only detected after a read would exceed the end of the file. This is why you get your invalid value twice, the second time the read fails and simply leaves temp with it's previous value. See this question for a more details.

Community
  • 1
  • 1
François Andrieux
  • 24,129
  • 6
  • 46
  • 72
  • The value 9 is actually `\t`. 10 is `\n`. The fact that both are considered white space is what causes the issue. – IInspectable Mar 01 '17 at 19:01
  • Or rather, `readFile >> ws` skips over the `\t` character only, then reading the four bytes `00 00 00 0a`, interpreted as a little-endian 4-byte integer is the value 167772160. This is still well defined (I believe). However, the next read attempt reads beyond the EOF. That is UB, and displaying 167772160 is a valid form of undefined behavior. – IInspectable Mar 01 '17 at 19:06
1

The answer by François Andrieux already has the answer to the question of why your code behaves the way it does.

Here are couple of methods to fix the problem.

  1. Use a for loop to read the numbers. It mirrors the loop used to write to it.

    readFile.open("file.dat", ios::binary);
    for (int i = 5; i <= 10 ; i++)
    {
       readFile.read((char*)(&temp), sizeof(temp));
       cout << "temp: " << temp << endl;
    }
    readFile.close();
    
  2. Use the while loop correctly.

    readFile.open("file.dat", ios::binary);
    while (readFile.read((char*)(&temp), sizeof(temp)))
    {
       cout << "temp: " << temp << endl;
    }
    readFile.close();
    
Community
  • 1
  • 1
R Sahu
  • 196,807
  • 13
  • 136
  • 247