Witam, potrzebuje pomocy w moim projekcie aby zapisać obiekty do plików binarnych. Jest to projekt na studia i niestety mam trochę narzucone, że muszą to być pliki binarne.
Generalnie nie miałem problemów z takim zapisem i odczytem gdy miałem zapisać wektor obiektów, które nie są bardziej skomplikowane. Jednak problem się pojawia, gdy chce zapisać do pliku wektor obiektów ContactBook, które w sobie posiadają jeszcze wektor obiektów Contact. Metody zapisu i odczytu z pliku są w klasie ContactBookModel, w której jest też ten wektor najbardziej nadrzędny. Pliki nagłówkowe dla lepszego zobrazowania zamieszczę poniżej.
Poniżej wstawiam kod metod zapisu i odczytu z pliku binarnego:
Najpierw do pliku zapisuje rozmiar wektora książek, następnie zapisuje po kolei każdy obiekt książki. Podczas wczytywania danych analogicznie wczytuje rozmiar wektora, a później tworzę nowe obiekty książek i dodaje je do wektora. Problem pojawia się właśnie podczas samego odczytu kontaktów.
void ContactBookModel::saveDataToFile(std::string fileName)
{
std::ofstream file(fileName, std::ios::binary | std::ios::trunc);
if (!file.is_open()) {
throw std::invalid_argument("Nie można otworzyć pliku");
}
size_t size = this->books.size();
file.write(reinterpret_cast<char*>(&size), sizeof(size));
for (auto& book : this->books) {
file.write(reinterpret_cast<const char*>(&book), sizeof(book));
}
file.close();
}
void ContactBookModel::loadDataFromFile(std::string fileName)
{
std::ifstream inputFile(fileName, std::ios::binary);
if (!inputFile.is_open()) {
throw std::invalid_argument("Nie można otworzyć pliku");
}
size_t numBooks;
if (!inputFile.read(reinterpret_cast<char*>(&numBooks), sizeof(numBooks))) {
throw std::invalid_argument("Błąd odczytu liczby obiektów!");
}
for (size_t i = 0; i < numBooks; i++) {
ContactBook book;
if (!inputFile.read(reinterpret_cast<char*>(&book), sizeof(book))) {
throw std::invalid_argument("Błąd odczytu ksiazki!");
}
this->books.push_back(book);
}
inputFile.close();
}
Poniżej zamieszczam kod debugera, pokazujący obiekt book, od razu po odczytaniu do niego danych z pliku. Wartości zmiennych dla książek - name oraz desc są wczytane prawidłowo. Rozmiar wektora contacts też się zgadza. Problemem jest to, że nie wczytują się poprawnie kontakty.
Wydaje mi się, że z samym zapisem do pliku nie ma problemu.
Jak widać wartości nie udało się odczytać, co w rezultacie podczas dodawanie tego obiektu do wektora pojawia się wyjątek który zamieściłem poniżej:
// klasa ContactBookModel
#pragma once
#include <vector>
#include "ContactBook.h"
#include <fstream>
// Model
class ContactBookModel {
private:
std::vector<ContactBook> books;
public:
std::vector<std::string> getBooksVstr();
void addBook(std::string name, std::string desc);
bool deleteBook(int index);
int getNumBooks();
void saveDataToFile(std::string fileName);
void loadDataFromFile(std::string fileName);
ContactBook* getBook(int index);
};
// klasa Contact
#pragma once
#include <iostream>
#include <string>
class Contact
{
private:
int id;
int phone_number;
std::string name;
std::string last_name;
std::string email;
public:
Contact();
Contact(int id, int phone_number, std::string name,
std::string last_name, std::string email);
void editContact(int phone_number, std::string name,
std::string last_name, std::string email);
void checkData(int phone_number, std::string name,
std::string last_name, std::string email);
void setId(int id);
void setPhoneNumber(int phone_number);
void setName(std::string name);
void setLastName(std::string last_name);
void setEmail(std::string email);
int getId();
int getPhoneNumber();
std::string getName();
std::string getLastName();
std::string getEmail();
std::string getContactStr();
};
// klasa ContactBook
#pragma once
#include "Contact.h"
#include <iostream>
#include <vector>
#include <string>
class ContactBook
{
private:
std::string name;
std::string desc;
std::vector<Contact> contacts;
public:
ContactBook();
ContactBook(std::string name, std::string desc);
~ContactBook();
void editBook(std::string name, std::string desc);
void checkData(std::string name, std::string desc);
bool addContact(int phone_number, std::string name, std::string last_name, std::string email);
bool removeContact(int id);
Contact* getContact(int index);
bool sortContacts();
int getNumContacts();
std::vector<Contact> getContacts();
std::vector <std::pair<int, std::string>> getContactPairs();
std::vector <std::string> getContactsVstr();
std::vector <std::pair<int, std::string>> searchContacts(std::string input, std::string formula);
std::string getName();
std::string getDesc();
void setName(std::string name);
void setDesc(std::string desc);
};
To samo rozwiązanie można powiedzieć, że działa na moim przykładowym projekcie. Gdzie robię to samo ale w trochę prostszej formie. Zamieszczam link do kodu na pastebin: https://pastebin.com/h7zhnuXz. Jedynym problem w tym kodzie było to, że wyskakiwał wyjątek, tyle, że podczas punktu return 0 w main.
Czy robiąc tym sposobem ma to w ogóle prawo działać? Może problem leży jeszcze w innej części programu?
Liczę na waszą pomoc w rozwiązaniu problemu.
@Edit Dodam jeszcze, że jak śledzę w debugerze zmienne, które zapisuje do pliku, to mają one poprawne wartości.