Search code examples
c++filebinaryfstreamifstream

Trying to read binary file clears the file itself


I just started working with binary files in C++, and i have successfully written and read a (.bin) file. Here is the code:

#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

int main()
{
    char input[100];

    strcpy(input, "This is a string");

    fstream file("example.bin", ios::binary | ios::in | ios::out | 
ios::trunc);

if(!file.is_open())
{
    cerr << "Error opening file.\n";
} else {
    for(int i = 0; i<= strlen(input); i++)
    {
        file.put(input[i]);
    }
}

file.seekg(0);
char ch;

while(file.good())
{
    file.get(ch);
    cout<<ch;
}
}

And this worked. After that, i tried to redesign the code to just read a binary file. The major changes were: changed fstream to be an ifstream(to read), deleted the part with writing into a file. Once the code was ready, i found a file i want to read (eof0.bin). When i used the code, the only thing i got was an empty string. I noticed that the initial size of the file was 37 kilobytes, while after using my program it became 0. I want to know, how my program cleared the data in the binary file?

This is the code that i used to read the file.

#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

int main()
{

ifstream file("eof0.bin", ios::binary | ios::in | ios::out | ios::trunc);

if(!file.is_open())
{
    cerr << "Error opening file.\n";
} else {
    // Nothing.
}

file.seekg(0);
char ch;

while(file.good())
{
    file.get(ch);
    cout<<ch;
}


}

Everything compiles, but using it on a file 37 kilobytes in size gives me a 0 kilobyte file.


Solution

  • You open with an openmode std::ios_base::trunc. From http://en.cppreference.com/w/cpp/io/ios_base/openmode we can see that it

    discard[s] the contents of the stream when opening

    So just use:

    // also dropped ios::out since you only want to read, not write
    ifstream file("eof0.bin", ios::binary | ios::in);
    

    Further, this

    char ch;
    while(file.good())
    {
        file.get(ch);
        cout<<ch;
    }
    

    is not an appropriate way to read the file. Think about what happens with an empty file: After opening it, it's "good" (remember, the eofbit is only set when some input operation encounters eof). Then the get fails, leaving ch as it is, thus invoking undefined behavior. Better test on the stream state directly after the input operation:

    char ch;
    while (file.get(ch)) {
      // use ch
    }
    // optionally distinguish eof and fail cases
    

    For more background on reading files, see Why is iostream::eof inside a loop condition considered wrong?