c++ read a saved objects in file.dat - c++

how should I proceed so that the function read, get reads the file.dat, whenever the file start?
I writing an object to the file, and I need to read when the program starts.
Problem: whenever I boot up the program to read the data once saved already, I have segmentation fault problems
void DataManip::DataManipWrite(DateAdress *writer) {
ofstream ObjectWriter;
ObjectWriter.open("dbaddress.dat", ios::binary);
ObjectWriter.write((char *)&writer, sizeof(writer));
ObjectWriter.close();
}
void DataManip::DataManipRead(DateAdress *reader) {
ifstream ObjectReader;
ObjectReader.open("dbaddress.dat", ios::binary);
ObjectReader.read((char *)&reader, sizeof(reader));
ObjectReader.close();
}

First, your sizeof operators return the size of the pointer instead of the class. Second, the class itself has to be a POD if you want to simply dump the memory to a file and read it later. Third, you're writing the value of the pointer itself, not the class data.

Related

how to write/read vector of A Class safely with fstream in C++?

Recently I got an annoying bug about read data into a vector of A Class.I have written a simple program to test the fstream in main function and it worked without any problem.
But while I coding a Book Class in Book.h and implement the Class in Book.cpp,then attempted to write vector of Book into a file with ofstream,no bug occurred.
//write data
ofstream output("book.bat",ios::binary);
if( !output ){
exit(-1);
}
output.write(reinterpret_cast<char*>(&books[0]),sizeof(Book)*books.size());
output.close();
//read data
ifstream input("book.bat",ios::binary);
if( !input ){
exit(-1);
}
Book tmp;
while( input.read(reinterpret_cast<char*>(&tmp),sizeof(Book)) ) {
books.push_back(tmp);
}
input.close();
Unfortunately when program run to the step of readding file into vector,the bug occurred.Having searched for some hours, I got nothing to deal with the bug.
Thanks for help.
For a point of view of class as a type that encapsulates the internal representation, to read/write using the direction of memory and size of the type is an error. This could work for POD types, but if book is a type with some data as pointers to dynamic memory, your code will not work.

Store and Load objects from a file

I'm making this program for class and we are supposed to store objects from a class in a file and then load them. But I always get the last object stored instead of the first. Tried the seekp function but it doesn't work. Also shouldn't the size of an object be 38 bytes, instead of the 48 i'm getting?
void student::load()
{
fstream fin;
fin.open("StudentData.bin",ios::binary|ios::in);
fin.read((char*)this,sizeof(*this));
}
void student::store(int z)
{
fstream fout;
fout.open("StudentData.bin",ios::binary|ios::out);
//fout.seekp(38*z, fout.beg)
cout<<sizeof(*this);
fout.write((char*)this,sizeof(*this));
}
for(i=0;i<count;i++)
{
s[i].store(i);
}
cout<<"Done!";
student pleb;
pleb.load();
pleb.showstudent();
return 0;
}
Your fout.open() rewrites the file each time. If you want to append to file, that is, to have each store() call to write that student after all other students already written, then you can use the ios::app flag.
Or, better, do not open the file in store() at all. Make your store() actuall accept the stream as a parameter; then open the file in the main program (once per all students) and pass the stream to store(). Not only this will solve your problem, but will also make your student class more configurable as it will be easy to write to any file, or in general to any stream the user of student needs.
BTW, also make sure that it is correct to write your students this way. For example, if you have any pointers in your student (including, say, std::string members as they have pointers inside), you will not get what you expect.
As for the object size, it is impossibly to answer not seeing the whole declaration of student class.

Reading objects from a binary file

I wrote a program, which lets you enter information about a car, and then writes the object on a binary file.
Car car_obj; std::ofstream entr; std::ifstream ex;
void save_data() {
entr.open("main.bin", std::ios::app | std::ios::binary);
car_obj.setInfo(); entr.write((char*)&car_obj, sizeof (car_obj));
entr.close();
}
After this, I have a function which is reading this binary file in order to display all cars which have fuel consumption less than what the user enters (the number is factr in the function arguments).
void vehicles_under_factr(float factr) {
ex.open("main.bin", std::ios::app | std::ios::binary);
while (ex.read((char*)&car_obj, sizeof (car_obj)) && !ex.eof()) {
if (car_obj.fuel_cons < factr) {
car_obj.displayInfo();
}
}
ex.close();
}
It works fine, but only if I have three, or less, objects in my binary file. When there are more than three, it displays the rest as empty fields. As if there is no access after the third car. Why is that so, and what can I do about it?
I feel close to the solution, but my knowledge is limited. Thank you in advance!
no, you can't do this,read((char *)obj, sizeof(obj)),because every object in program have itself memory address, allocate by system. you can't read address
from file .if your object only contain data, it work fine, but if it's element is a object and itself attribute related memory address or iterator(related memory address). it work fail.

How can I update record in file in c++?

In below mentioned code of function. I am not able to update balance(deposits and withdrawals) in file my.dat. Please advise where am I doing it wrong. (I am a newbie).
void dep_with(int e, int f)
{
int amt;
int recordFind=0;
account ac;
ifstream updatedata("E:\\c++ Project\\final thoughts\\my.dat", ios::in|ios::out);
while(updatedata.read((char*) &ac, sizeof(ac)) && recordFind==0)
{
if(ac.get_account()==e)
{
ac.view_account();
if(f==1)
{
cout<<"\nEnter the amount to be deposited";
cin>>amt;
ac.deposits(amt);
}
if(f==2)
{
cout<<"\nEnter the amount to be withdraw";
cin>>amt;
ac.withdrawls(amt);
}
int pos=(-1)*sizeof(ac);
ofstream updatedata("E:\\c++ Project\\final thoughts\\my.dat", ios::in|ios::out|ios::app);
updatedata.seekp(pos,ios::cur);
updatedata.write((char*) &ac, sizeof(ac));
cout<<"\n\n\tRecord Updated";
recordFind=1;
}
}
updatedata.close();
if(recordFind==0)
{
cout<<"\n\nRecord not Found";
}
}
There are a number of problems here. First, updatedata is a
std::ifstream, which means that it doesn't have functions like write
or seekp. Second, you've opened it in text mode, so you cannot seek
to an arbitrary position in the file; you can only seek to the beginning
or the end, or to a position which was returned by tellg or tellp.
(It's undefined behavior otherwise.) You'll have to memorize the
position before each read, and work from that.) Third, you don't show
the definition of account, but in general, you cannot use
istream::read and ostream::write directly on objects of the type:
you have to format the output and parse the input, using an intermediate
buffer.
EDIT:
I've just noticed that you actually open the file a second time for
writing. This cannot be made to work for several reasons, not the least
of which is that some systems will not allow opening a file with write
access if the file is already open elsewhere. Other than that: you open
with std::ios_base::app, which means that all writes will append to
the end of the file, regardless of where the position marker was before.
In summary:
You need to use an std::fstream.
You need to memorize the position (using tellg) before each read,
and seek back to it if you want to write.
You need to use an intermediate buffer for the data. (This may not
be necessary if 1) the program which reads and writes the data is
compiled with the same compiler, using the same options, on the same
machine, running under the same OS, and 2) the data structure is a pure
POD. These conditions are almost never met in well written C++.)

C++ program.exe has stopped working after reading from binary file

I have made a class Flight with informations to be stored in a binary file called data.txt at another method.That saving of records was working fine, but now I'm having problems reading back the records I've saved. It is working to display all the records till the end of the file (eof). But when records are done displaying, there comes a pop up error saying that Program.exe has stopped working.
void Flight::ViewFlight(){
HANDLE hConsole; //Console colors
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
fstream data;
Flight flight;
data.open("data.txt",ios::in | ios::binary);
if (data.fail())
{
SetConsoleTextAttribute(hConsole, 12);
cout<<"\n\nFlight data does not exist yet";
cout<<"\n\nYou are being redirected to the Main Menu in 3 seconds\n\n";
cout<<"3\n\n";
Sleep(1000);
cout<<"2\n\n";
Sleep(1000);
cout<<"1\n\n";
Sleep(1000);
cout<<"0\n\n";
SetConsoleTextAttribute(hConsole, 15);
}
else{
while(data.read((char*) &flight, sizeof(flight)))
{
if(!data.eof())
{
SetConsoleTextAttribute(hConsole, 10);
cout<<"\n\n----------- Record for "<<flight.flightid<<" -----------\n";
SetConsoleTextAttribute(hConsole, 15);
cout<<"\nFlight Number \t\t: "<<flight.flightnumber;
cout<<"\nDeparture Airport\t: "<<flight.departAirport;
cout<<"\nArrival Airport\t\t: "<<flight.arriveAirport;
cout<<"\nDeparture Time\t\t: "<<flight.departTime.hour<<":"<<flight.departTime.minute;
cout<<"\nDeparture Date\t\t: "<<flight.departDate.day<<"/"<<flight.departDate.month<<"/"<<flight.departDate.year;
cout<<"\nPrice \t\t\t: RM "<<flight.price;
cout<<"\nBusiness Class Seats\t: "<<flight.bseat;
cout<<"\nFirst Class Seats\t: "<<flight.fseat;
cout<<"\nEconomy Class Seats\t: "<<flight.totalseat;
cout<<endl;
}
}
}
data.close();
}
Your Flight class contains std::string members. These are not plain old data types and typically hold pointers to dynamically allocated memory. You can't read and write your class as a unit and hope the std::string members and their contents will be properly constructed. The same may apply to the Time and Data members but you haven't shown how they're defined.
You need to look into proper serialization.
Several related questions:
Serializing a class which contains a std::string
How to write strings as binaries to file?
Question about read and write std::string to Binary Files
The loop seems fine, your file might have corrupted data, probably a not terminated string, or may be there is/are some garbage characters at the end of the input file. to verify comment all the cout statements in the loop, and see if the program stops hanging.
also data.eof() check is redundant, nevertheless it should not hang the program.
just had a look at your flight class, you can not read directly into a class having other class objects. in your case, the string objects. you need to deserliaze the stream and initilize the variables yourself
The problem is when the Flight is getting destructed it is destroying those string objects which are not correctly constructed string objects.
Basically first separate your character strings from your buffer and assign those to your string variables one by one yourself.
Flight structure consist of other classes that point to dynamically allocated memory (heap), for example string flightnumber; is STL string class, that has char* or wchar* inside.
If you save Flight object as a binary buffer, it will save pointer only. While loading the object, you'll get memory address in the pointer, that is invalid. That's the reason you are getting access violation exception, that means you tried to access not allocated memory.
btw that's the best case you got 0xC0000005, in worst case you'd just access memory allocated for other objects, and got trash in your output.
You have to overload operator<< and operator>> for Flight class, and every class member which is not standard library. After you do it you'll just write:
fstream data;
Flight flight;
data >> flight;