C чтение / запись объектов с помощью двоичных файлов

#c #binaryfiles

#c #двоичные файлы

Вопрос:

Я потратил часы времени, пытаясь решить проблему манипулирования двоичными файлами.

Задача состоит в том, чтобы читать и записывать объекты BookStoreBook в / из двоичного файла

Класс BookStoreBook содержит следующие переменные-члены:

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

Код для чтения книг выглядит так, как показано на рисунке:

 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));
}
 

Код для написания книг выглядит так, как показано на рисунке:

 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 = amp;writeBooks[i];
     file.write((char*)book, sizeof(BookStoreBook));
     file.clear();
}
file.clear();
file.close();
 

Я не хочу преобразовывать какую-либо строку в c_str(), поскольку это запрещено в требованиях к назначению.

Некоторые примечания:

Сразу после запуска программы программа пытается прочитать книги из файла, и именно тогда мы получаем окно ошибки Windows, позже, когда я выполняю отладку, я получаю следующее сообщение: Необработанное исключение в 0x56b3caa4 (msvcr100d.dll ) в FinalProject.exe : 0xC0000005: Местоположение чтения с нарушением доступа 0x0084ef10

Забавно, что иногда программа работает отлично, а иногда происходит сбой при первом чтении книг из файла.

Однако всякий раз, когда программа успешно считывает некоторое содержимое, и я не изменяю книги, а затем снова открываю программу, программа продолжает работать отлично.

Кажется, ничего не работает. Пожалуйста, помогите!

Комментарии:

1. Вы хотите запустить свою программу в отладчике.

2. Когда ваш подход сериализует указатели, вы сериализуете сам указатель, но не то, на что он указывает. Вот что здесь происходит, если string означает std::string .

3. на самом деле, я получил это сообщение об ошибке через отладчик Visual Studio

4. как выглядят классы для Author и Date?

5. BookStoreBook не является POD, поскольку он наследует класс, содержащий виртуальные функции, и имеет конструктор

Ответ №1:

Ваша проблема здесь в том, что определенные части вашего BookStoreBook класса содержат указатели, даже если они не видны. std::string например, имеет указатель на ячейку памяти, где хранится содержимое строки.

Практически всегда считается плохой практикой записывать структуры данных на C на диск по мере их появления в памяти. При этом не учитывается разный порядковый номер на разных машинах, ширина слова на разных машинах ( int или long может отличаться по размеру на 32-битных и 64-битных машинах), и вы сталкиваетесь со всеми проблемами с указателями.

Вы должны поместить каждое из ваших полей BookStoreBook в выходной поток в соответствии с

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

Обратите внимание, что это очень плохая практика, поскольку декодирование становится ужасно сложным. Я предлагаю вам использовать Boost.Сериализация для этого или напишите свои собственные методы, которые могут считывать / записывать пары ключ-значение из файла, или вы можете заглянуть в jsoncpp или tinyxml2. Вся эта тема может стать довольно запутанной, поэтому придерживаться Boost — хорошая идея, даже если просто выяснить, как решить проблему самостоятельно (предполагая, что это домашнее задание).