Search code examples
c++binaryfiles

Reading binary file created by another set of codes c++


Hi im trying to read in a binary file that i created from another set of codes. Eg. Using A.cpp to create the binary file and using B.cpp to read the file

For example: in A.cpp i have created a file using with following structure below

struct assignment
{
    char atitle [MAX];
    int weight;
    int markupon;
    double marks;    
};

struct subjects
{
    char code [MAX];
    char subtitle [MAX];
    int NoOfTask;
    assignment AStructure [MAX];
    int finalmarks;
    grades grade;   
};

In A.cpp i use the following code to get the number of records i have in the file and it works fine.

int getNoOfRecords (fstream& afile, char filename [])
{
    afile.open (filename, ios::in | ios::binary);

    if (!afile)
    {
        afile.close ();

        return 0;
    }

    // move read marker point to end of
    // the last record
    afile.seekg (0, ios::end);

    int totalBytes = afile.tellg ();

    int noOfsubjects = totalBytes / sizeof (subjects);

    afile.close ();
    return noOfsubjects;
}

In B.cpp i have the following structures

struct studentassignment
{
    char atitle [MAXN];
    int weight;
    int markupon;
    double marks;    
};

struct studentsubjects
{
    char code [MAXN];
    char subtitle [MAXN];
    int NoOfTask;
    studentassignment AStructure [MAXN];
    int finalmarks;
    char grade [MAXN];   
};*

And in B.cpp i use the below code to get the number of records but the results im getting is different from what i get in A.cpp. For example: I enter 3 sets of data in A.cpp, when i read from B.cpp i only get a size of 2. The data that is read in from the file is incorrect too.

int NoOfRecords (fstream& afile, char filename [])
{
    afile.open (filename, ios::in | ios::binary);

    if (!afile)
    {
        afile.close ();

        return 0;
    }

    afile.seekg (0, ios::end);

    int totalBytes = afile.tellg ();

    int noOfsubjects = totalBytes / sizeof (studentsubjects);

    afile.close ();
    return noOfsubjects;
}

Is there something that im doing wrong or is there just no way to read in the file using a different cpp file??

Im only a beginner at c++ if im wrong at anything pls let me know. thanks in advance

MVCE

A.cpp

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <iomanip>

using namespace std;

const int MAX = 80;

enum grades {HDist, Dist, Credit, Pass, Fail};


struct assignment
{
    char atitle [MAX];
    int weight;
    int markupon;
    double marks;    
};


struct subjects
{
    char code [MAX];
    char subtitle [MAX];
    int NoOfTask;
    assignment AStructure [MAX];
    int finalmarks;
    grades grade;   
};

int main ()
{

    afile.open ("filename.dat", ios::out | ios::binary);
    afile.seekg (0, ios::end);

    subjects s;

    cout << "Subject Code: ";
    cin >> s.code;      
    cout << "Subject Name: ";
    cin.ignore();
    cin.getline(s.subtitle, MAX);
    cout << "No of assessment task: ";
    cin >> s.NoOfTask;
    cout << endl;
    for (int i = 0; i < s.NoOfTask; i++)
    {
        cout << "Task " << i+1 << " information" <<endl;
        cout << "Title: ";
        cin.ignore();
        cin.getline(s.AStructure[i].atitle, MAX);

        cout << "Weight: ";
         cin >> s.AStructure[i].weight;
        cout << "Upon: ";
        cin >> s.AStructure[i].markupon;
        cout << endl;
        s.AStructure[i].marks = 0;

        total = total + s.AStructure[i].weight;
    }

    afile.write (reinterpret_cast <const char *>(&s), sizeof (subjects));

    afile.close ();
}

B.cpp

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <iomanip>


using namespace std;

const int MAXN= 80;
const int MAXN0= 10;

struct studentassignment
{
    char atitle [MAXN];
    int weight;
    int markupon;
    double marks;    
};

struct studentsubjects
{
    char code [MAXN];
    char subtitle [MAXN];
    int NoOfTask;
    studentassignment AStructure [MAXN];
    int finalmarks;
    char grade [MAXN];   
};

int NoOfRecords (fstream& , char []);
void getrecord(fstream& afile, char filename [] , int, studentsubjects);

int main()
{
    fstream afile;
    subjects b;
    int size;

    size = NoOfRecords (afile, "filename.dat");
    cout << size << endl;

    for (int i = 0; i < size; i++)
    {
        getrecord(afile, "filename.dat", i+1, b);
        cout << b.code << endl;
    }

}


 int NoOfRecords (fstream& afile, char filename [])
{
    afile.open (filename, ios::in | ios::binary);

    if (!afile)
    {
        afile.close ();

        return 0;
    }

    afile.seekg (0, ios::end);

    int totalBytes = afile.tellg ();

    int noOfsubjects = totalBytes / sizeof (studentsubjects);

    afile.close ();
    return noOfsubjects;
}

void getrecord(fstream& afile, char filename [], int i, studentsubjectsb)
{
    afile.open (filename, ios::in | ios::binary);



    afile.seekg ((i) * sizeof (studentsubjects), ios::beg);

    afile.read (reinterpret_cast < char *>(&b), sizeof (studentsubjects));

    afile.close ();

}

Solution

  • The last member in struct subjects (used in A.cpp) is grade and it should be around 1-8 bytes.
    The last member in struct studentsubjects (used in B.cpp) is char[80] and it should be 80 bytes. It means that the structure in B.cpp will be bigger than one in A.cpp.

    As a result, if the same number of bytes are given and it is just the size of three struct subjects, it won't sufficient for three struct studentsubjects.

    To avoid this type of mistake, you should write the declaretions of structures to read and write in a header file and use the header file from source codes that read and/or write the structures.