Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Problems when reading binary files in C++

Here is a code to generate a binary file "input" :

#include <fstream>
int main() {
    unsigned char buf[] = {
        0x06, 0x00, 0x00, 0x00, 0x62, 0x6f, 0x79, 0x31, 0x00, 0x00, 0x00, 0x00,
        0x6d, 0x0f, 0x00, 0x00, 0xc8, 0x42, 0x9a, 0x99, 0xd9, 0x3f, 0x62, 0x6f,
        0x79, 0x32, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x10, 0x00, 0x00, 0xa0, 0x42,
        0x9a, 0x99, 0xd9, 0x3f, 0x62, 0x6f, 0x79, 0x33, 0x00, 0x00, 0x00, 0x00,
        0x6d, 0x11, 0x00, 0x00, 0x70, 0x42, 0x9a, 0x99, 0xd9, 0x3f, 0x62, 0x6f,
        0x79, 0x34, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x12, 0x00, 0x00, 0x20, 0x42,
        0x9a, 0x99, 0xd9, 0x3f, 0x67, 0x69, 0x72, 0x6c, 0x31, 0x00, 0x00, 0x00,
        0x66, 0x13, 0x00, 0x00, 0x48, 0x42, 0x9a, 0x99, 0xd9, 0x3f, 0x67, 0x69,
        0x72, 0x6c, 0x32, 0x00, 0x00, 0x00, 0x66, 0x13, 0x00, 0x00, 0x48, 0x42,
        0x9a, 0x99, 0xd9, 0x3f};
    std::ofstream fout("input", std::ofstream::binary);
    fout.write((char *)buf, sizeof(buf));
    fout.close();
    return 0;
}

The details are as : The first 0x06 indicates how many records are there, and the follows are some records, each with name, gender(‘m’ or ‘f’), age, weight and height.

To read this binary file in c++, I created a struct :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct Person{
    unsigned char name[8];
    unsigned char gender;
    unsigned int age;
    float weight,height;
}person[100];

And the code fragment below is how I read this file :

using namespace std;
ifstream fin;
fin.open("input",ios::binary);

int n;
fin.read(reinterpret_cast<char*>(&n),sizeof(n));

for(int i=0;i<n;i++)
     fin.read(reinterpret_cast<char*>(&person[i]),sizeof(person[i]));

and I try to make an ouput, but then it appears garbled codes :

code:
for(int i=0;i<n;i++)
     cout<<person[i].name<<' '<<person[i].gender<<' '<<person[i].age<<' '<<person[i].weight<<' '<<person[i].height<<endl;

output:
boy1  2577023688 7.00208e+28 1.81062e-41
 � 863596386 0 6.25119e-42
pB���?boy4  309133312 40 1.7
girl1  2577023560 1.74727e+25 4.63068e-39
 � 0 0 0
  0 0 0

and this makes me really comfused. Can someone explain why this will happen and how to solve it?

>Solution :

You have several problems.

First, the name is 8 characters, not 10. Second, the age is only one byte, not 4 bytes. Third, because you have mixed types, you are getting padding within the structure that messes things up. You need to declare it as "packed":

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

struct Person{
    char name[8];
    char gender;
    unsigned char age;
    float weight,height;
} __attribute__((packed)) person[100];

int main()
{
    ifstream fin;
    fin.open("input",ios::binary);

    int n;
    fin.read(reinterpret_cast<char*>(&n),sizeof(n));
    cout << "Reading " << n << " records\n";
    cout << "Each is " << sizeof(Person) << " bytes\n";

    for(int i=0;i<n;i++)
        fin.read(reinterpret_cast<char*>(&person[i]),sizeof(person[i]));

    for(int i=0;i<n;i++)
        cout<<person[i].name<<" "<<person[i].gender<<" "<<(int)person[i].age<<" "<<person[i].weight<<" "<<person[i].height<<endl;
}

Output

Reading 6 records
Each is 18 bytes
boy1 m 15 100 1.7
boy2 m 16 80 1.7
boy3 m 17 60 1.7
boy4 m 18 40 1.7
girl1 f 19 50 1.7
girl2 f 19 50 1.7

In Windows, you’d use #pragma packed(1) instead of the attribute.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading