#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 — хорошая идея, даже если просто выяснить, как решить проблему самостоятельно (предполагая, что это домашнее задание).