954,535 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Reading a Binary File to a C++ Class

Is it possible to read data from a binary file to a C++ class using istream::read ? I know it can be done for structures, but I couldnt do it for a class.

[Edit]
Want code?

#include <iostream>
#include <fstream>

class BITMAPFILEHEADER
{
private:
    char                type[ 2 ];              // Magic identifier
    unsigned int        size;                   // File size in bytes
    unsigned short int  reserved1;              // Reserved; always zero
    unsigned short int  reserved2;              // Reserved; always zero
    unsigned int        offset;                 // Offset to image data, bytes

public:
    friend std::istream& operator>>(std::istream& s, BITMAPFILEHEADER& r);
};
std::istream& operator>>(std::istream& s, BITMAPFILEHEADER& r);
std::istream& operator>>(std::istream& s, BITMAPFILEHEADER& r)
{
#if 0
    // This does not work
    s.read( reinterpret_cast <char*>(&r), sizeof(BITMAPFILEHEADER) );
    if( s.bad() )
    {
        std::cerr << "Error reading data" << std::endl;
        exit( 0 );
    }
#endif
#if 1
     // This works
    s.read( r.type, 2 * sizeof(char) );
    if( s.bad() )
    {
        std::cerr << "Error reading data" << std::endl;
        exit( 0 );
    }

    s.read( (char*)&(r.size), sizeof(unsigned int) );
    if( s.bad() )
    {
        std::cerr << "Error reading data" << std::endl;
        exit( 0 );
    }

    s.read( (char*)&(r.reserved1), sizeof(unsigned short int) );
    if( s.bad() )
    {
        std::cerr << "Error reading data" << std::endl;
        exit( 0 );
    }

    s.read( (char*)&(r.reserved2), sizeof(unsigned short int) );
    if( s.bad() )
    {
        std::cerr << "Error reading data" << std::endl;
        exit( 0 );
    }

    s.read( (char*)&(r.offset), sizeof(unsigned int) );
    if( s.bad() )
    {
        std::cerr << "Error reading data" << std::endl;
        exit( 0 );
    }
#endif

    return s;
}
WolfPack
Postaholic
Moderator
2,051 posts since Jun 2005
Reputation Points: 572
Solved Threads: 115
 

I think it is better to take the serialized approach you presented. Even with a POD structure the binary read/write is inherently non-portable.

Nit - consider this:

s.read( r.type, sizeof r.type );
//s.read( r.type, 2 * sizeof(char) );

// ...

s.read( (char*)&(r.size), sizeof r.size );
//s.read( (char*)&(r.size), sizeof(unsigned int) );


And FWIW: http://www.parashift.com/c++-faq-lite/serialization.html#faq-36.6

Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 

Okay. Got it. Thanks for the additional info too.

WolfPack
Postaholic
Moderator
2,051 posts since Jun 2005
Reputation Points: 572
Solved Threads: 115
 

I think it is better to take the serialized approach you presented. Even with a POD structure the binary read/write is inherently non-portable.

Nit - consider this:

s.read( r.type, sizeof r.type );
//s.read( r.type, 2 * sizeof(char) );

// ...

s.read( (char*)&(r.size), sizeof r.size );
//s.read( (char*)&(r.size), sizeof(unsigned int) );
And FWIW: http://www.parashift.com/c++-faq-lite/serialization.html#faq-36.6

sometimes in reading binary files, you may want take a byte of data and store it into something bigger. Then it is NOT good to use the sizeof( ) to specify how much of the file to read. EX. what if you want to read 1 byte of the file into an" integer size" class variable, r::int var1? using the sizeof(r.var1) in the read statement would indicate that 4 bytes are to be read instead of just 1 byte. this will throw off the parsing of the file.

bbowles2
Newbie Poster
1 post since Feb 2010
Reputation Points: 32
Solved Threads: 0
 

This is your lucky day -- I gave you positive instead of negative rep for bumping a 4-year-old thread

If you only read one byte into a 4-byte integer that would make the integer not worth shit. You can't do it like that (at least so that it will produce a valid integer). First read the byte into a char variable, then typecast the char into the integer. The sizeof operator will still work because sizeof(char) = 1.

Ancient Dragon
Retired & Loving It
Team Colleague
30,050 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You