Читать класс в двоичном формате - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь прочитать мой класс в двоичном формате, например:

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

Но я получаю ошибку: программа вылетает. Файл существует, а данные записаны так:

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

Этот код работает без ошибок. Помогите пожалуйста: (

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

На самом деле проблема заключалась в том, что класс Dog включает поле QString, которое ни одна программа не знает, сколько байтов нужно прочитать (строки "asd" и "asdasdasdasdasdasdsad" возвращают разные syzeof).Отсюда и ошибка.Это действительно правильно делать что-то вроде:

    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);
0 голосов
/ 17 мая 2018

Попробуйте это исправление:

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

В приведенном выше фрагменте я использую поток C ++, чтобы открыть файл. Смешивать потоки в стиле C ++ и C - плохая идея.

Цикл основан на успешном чтении из потока. Если чтение не удалось, цикл прекращается.

Данные считываются в локальную переменную, а затем добавляются в базу данных. Нет необходимости выделять память, потому что std::vector добавит copy в контейнер.

Вы можете заменить std::list на std::vector, но используйте соответствующий метод для добавления в список.

Для получения дополнительной информации поищите в Интернете "сериализацию C ++" и "сериализацию C ++ QT".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...