Daniel
Daniel

Reputation: 55

issue reading an object from a binary file in c++

I have a problem with reading from binary files. My homework is to manage a file system of a video library store.

I have a class "Client" (the code is below), and right now I am only trying to understand how the write() and read() functions work, so I am "playing" with them in my main().

First I am opening a file and writing 60 empty records into it. Then I am writing a few clients into the file.

when I try to read one client record, from a given position in the file into another existing client object - it reads two records...

I have tried and read almost everything and I haven't found an answer.

If I am trying to read a record into an empty client object, it is full of binary garbage.

#pragma once
#include <time.h>
#include <string>
#include <iostream>
using namespace std;

class Client
{
    private:
        char id[10];                        //client info
        char name[20];
        char address[40];
        char phoneNum[11];                  
        time_t startMembership;             //variable that represents the beginning of the membership in the library
        time_t endMembership;               //variable that represents the end of the membership in the library     
        int fines;


    public:
        Client() {};
        Client(char id[10],char name[20],char address[40],char phone[10],int fines);    //constructor 
        int     getFines()                              {return this->fines;}                                           //getters
        char*   getId()                                 {return this->id;}
        void    setName(char* newName)                  {strcpy(this->name,newName);}
        void    setId(char* newId)                      {strcpy(this->id,newId);}                                       //setters
        void    setAddress(char* newAddress)            {strcpy(this->address,newAddress);}
        void    setPhone(char* newPhone)                {strcpy(this->phoneNum,newPhone);}
        void    setStartMembership(time_t newStartDate) {this->startMembership = newStartDate;}
        void    setEndMembership(time_t newEndDate)     {this->endMembership = newEndDate;}
        void    setFines(int newFines)                  {this->fines = newFines;}
        bool    finesChecking();                                                                                        //true= need to pay

        friend ostream& operator<<(ostream& os, const Client& c);
        ~Client();                                                                                                  //distructor    
};


#include "Client.h"

/**
* Constructor
*/
Client::Client(char id[10],char name[20],char address[40],char phone[10],int fines)
{
    strcpy(this->id,id);
    strcpy(this->name,name);
    strcpy(this->address,address);
    strcpy(this->phoneNum,phone);
    this->fines = fines;
    time(&this->startMembership);       // the time in the binary file will be represented as raw time
    time(&this->endMembership);         
    this->endMembership += 30*24*60*60; // set the expiration date of the membership (1 month)
}

ostream& operator<<(ostream& os, const Client& c)
{
    os<<"ID: "<<c.id<<endl;
    os<<"Name: "<<c.name<<endl;
    os<<"Phone#: "<<c.phoneNum<<endl;
    os<<"Address: "<<c.address<<endl;
    os<<"Member Since: "<<ctime(&c.startMembership);
    os<<"Membership Exp: "<<ctime(&c.endMembership);
    os<<"Fines: "<<c.fines<<" ILS"<<endl;
    return os;
}

/**
* Distructor
*/
Client::~Client()
{
    delete[] this->address;
    delete[] this->id;
    delete[] this->name;
    delete[] this->phoneNum;
}


#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include "Menu.h"
#include "MovieCatalog.h"
#include "Client.h"

using namespace std;

int main()
{
    /*Menu menu;
    menu.StartMenu();*/

    Client *first, *second, *third, *fourth, *fifth;
    first = new Client("1","first","Lod","1",50);
    second = new Client("2","second","Herzelia","2",50);
    third = new Client("3","third","Holon","3",50);
    fourth = new Client("4","fourth","Haifa","4",50);
    fifth = new Client("5","fifth","Raanana","5",50);

    fstream file;
    Client blankClient;
    blankClient.setId("0");

    file.open("example.bin", fstream::out | fstream::binary);
    streampos pos;
    for(int i=1; i<=60; i++)
    {
        file.write((char*)&blankClient, sizeof(Client));
    }
    file.close();

    file.open("example.bin", fstream::out | fstream::binary);
    file.write((char*)&first,sizeof(Client));
    file.write((char*)&second,sizeof(Client));
    file.write((char*)&third,sizeof(Client));
    //put fourth and fifth @ 10th and 11th records
    file.seekp(sizeof(Client)*10,ios_base::beg);
    file.write((char*)&fourth,sizeof(Client));
    file.write((char*)&fifth,sizeof(Client));
    file.close();

    file.open("example.bin", fstream::in | fstream::binary);
    //put the "get" pointer on the 11th record (where "fifth" is located)
    file.seekg(sizeof(Client)*11,ios_base::beg);
    //read "fifth" object into "second" object
    file.read((char*)&second,sizeof(Client));
    file.close();
    cout<<*first;
    cout<<*second;
    //here you can see that it takes "fifth" and put it into "second", and the record prior to fifth ("fourth"), into "first"
    return 0;
}

Upvotes: 0

Views: 3516

Answers (1)

Mr.Anubis
Mr.Anubis

Reputation: 5322

given declaration : first = new Client("1","first","Lod","1",50);

Your writing method is incorrect:

file.write((char*)&first,sizeof(Client));
file.write((char*)&second,sizeof(Client));
...

so you're writing addresses of pointer not object itself, make it like :

 file.write((char*)first,sizeof(Client));
 file.write((char*)second,sizeof(Client));
 ...

same for line :

file.read((char*)&second,sizeof(Client)); -> file.read((char*)second,sizeof(Client));

also you're destructor is incorrect Client::~Client(), rather you don't need in your case

Upvotes: 2

Related Questions