-2

I have gone through hours of time trying to fix the issue of binary file manipulation.

The task is to read and write BookStoreBook objects to/from a binary file

The BookStoreBook class contains the following member variables:

string isbn;
string title;
Author author;
string publisher;
Date dateAdded;
int quantityOnHand;
double wholesaleCost;
double retailPrice;

The code for reading books is as shown:

fstream file("inventory.txt", ios::binary | ios::in | ios::out);    
vector<BookStoreBook> books:
BookStoreBook *book = (BookStoreBook *)new char[sizeof(BookStoreBook)];
file.read((char*)book, sizeof(BookStoreBook));
while (!file.eof())
{
     books.push_back(*book);
     file.read((char*)book, sizeof(BookStoreBook));
}

The code for writing books is as shown:

vector<BookStoreBook> writeBooks = library.getBooks(); //library contains books
file.close();
file.open("inventory.txt", ios::out | ios::binary);

for(int i = 0; i < writeBooks.size(); i++)
{
     BookStoreBook *book = (BookStoreBook *)new char[sizeof(BookStoreBook)];
     book = &writeBooks[i];
     file.write((char*)book, sizeof(BookStoreBook));
     file.clear();
}
file.clear();
file.close();

I don't want to convert any string to a c_str(), as this is prohibited in the assignment requirements.

Some notes:

Right when I run the program, the program tries to read books from the file, and that is when we get a Windows error window, later when i debug, i get the following message: Unhandled exception at 0x56b3caa4 (msvcr100d.dll) in FinalProject.exe: 0xC0000005: Access violation reading location 0x0084ef10

The funny thing is, sometimes the program runs perfectly fine, and sometimes it crashes when it first reads the books from the file.

However, whenever the program has successfully read some contents, and I dont modify the books, and then reopen the program, the program keeps running perfectly.

Nothing seems to work. Please help!

STIG
  • 11
  • 2

1 Answers1

4

Your problem here is that certain parts of your BookStoreBook class contain pointers, even though they are not visible. std::string for example has a pointer to the memory location where the contents of the string are kept.

It is virtually always considered a bad practice to write data structures in C++ to disk as they appear in memory. Doing this does not account for different endianness of different machines, word width on different machines (int or long may differ in size on 32bit and 64bit machines), and you run into all the pointer trouble.

You should push each of the fields of your BookStoreBook to the output stream, along the lines of

file << book.isbn << ' ';
file << book.title << ' ';
...

Note that the above is very bad practice, as the decoding gets horribly difficult. I suggest you use Boost.Serialization for this, or write your own methods that can read/write key-value-pairs from a file, or you might want to look into jsoncpp or tinyxml2. This whole topic can get quite convoluted, so sticking with Boost is a good idea, even if just to figure out how to solve the issue yourself (assuming this is a homework assignment).

Fabian Schuiki
  • 1,268
  • 7
  • 18