1

I'm trying to read my class in binary format like this:

FILE* file = fopen(filePath.toStdString().c_str(), "rb");
if (file == NULL)
{
    QMessageBox::critical(this, "Ошибка!", "Ошибка при открытии файла!");
    return;
}

while (!feof(file))
{
    Dog* dog;
    fread(dog, sizeof(Dog), 1, file);
    _list->emplace_back(dog);
}
fclose(file);

But I get an error: the program crashes. The file exists and the data is written like this:

FILE* file = fopen(filePath.toStdString().c_str(), "wb");
if (file == NULL)
{
    QMessageBox::critical(this, "Ошибка!", "Ошибка при открытии файла!");
    return;
}

for (int i = 0; i < _list->size(); i++)
{
    fwrite(_list->get(i), sizeof(Dog), 1, file);
}
fclose(file);

This code runs without errors. Help please :(

garbart
  • 465
  • 4
  • 19

2 Answers2

1

Actually the problem was that the Dog class includes a field QString, which no program knows how many bytes to read (the string "asd" and "asdasdasdasdasdasdsad" return different syzeof). Hence the mistake. It's actually right to do something like:

    FILE* file = fopen(filePath.toStdString().c_str(), "rb");

    while (!feof(file))
    {
        int nameSize;
        QString name;
        int breedSize;
        QString breed;
        int weigth;
        QDate birthDate;

        fread(&nameSize, sizeof(int), 1, file);
        for (int i = 0; i < nameSize; i++)
        {
            QChar ch;
            fread(&ch, sizeof(QChar), 1, file);
            name += ch;
        }

        fread(&breedSize, sizeof(int), 1, file);
        for (int i = 0; i < breedSize; i++)
        {
            QChar ch;
            fread(&ch, sizeof(QChar), 1, file);
            breed += ch;
        }

        fread(&weigth, sizeof(int), 1, file);
        fread(&birthDate, sizeof(QDate), 1, file);
        _list->emplace_back(new Dog(name, breed, weigth, birthDate));
   }
   fclose(file);
garbart
  • 465
  • 4
  • 19
0

Try this correction:

std::ifstream data_file("my_dogs.dat", ios::binary);
Dog d;
std::vector<Dog> database;
while (data_file.read((char *) &d, sizeof(Dog)))
{
  database.push_back(d);
}

In the above fragment, I'm using the C++ stream to open the file. Mixing C++ and C-style streams is a bad idea.

The loop is based on the success of reading from the stream. If the read fails, the loop is terminated.

The data is read into a local variable, then appended to the database. No need to allocate memory, because std::vector will append a copy to the container.

You could substitute std::list for std::vector, but use the appropriate method for appending to the list.

Search the internet for "C++ serialization" and "C++ QT serialization" for more information.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154