Сохраните и загрузите QList<Class *> в файл

У меня есть класс ContactData и класс FriendList, содержащий QList, и я перегружен операторами << / >>.


contactdata.h

class ContactData
{
//all public for testing
public:
    ContactData();
    QString m_name;
    QString m_description;
    bool m_online; 
};

QDataStream &operator<<(QDataStream& out, ContactData& contactData);
QDataStream &operator>>(QDataStream& in, ContactData* contactData);

contactdata.cpp

QDataStream &operator<<(QDataStream &out, ContactData& contactData)
{
    out << contactData.m_name;
    out << contactData.m_description;
    return out;
}

QDataStream &operator>>(QDataStream &in, ContactData* contactData)
{
    in >> contactData->m_name;
    in >> contactData->m_description;
    return in;
}

friendlist.h

#include "contactdata.h"
typedef QList<ContactData*> TFriendList;

class FriendList
{
...
public:
TFriendList* m_list;
...
};

QDataStream &operator<<(QDataStream& out, FriendList& list);
QDataStream &operator>>(QDataStream& in, FriendList* list);

friendlist.cpp

QDataStream &operator<<(QDataStream& out, FriendList& list)
{
    for(int i = 0; i < list.size(); i++)
    {
        ContactData contact = *list.at(i);
        out << contact;
    }

    return out;
}

QDataStream &operator>>(QDataStream& in, FriendList* list)
{
    for(int i = 0; i < list->size(); i++)
    {
        ContactData* contact = list->m_list->at(i);
        in >> contact;
    }

    return in;
}

// typedef QList<ContactData*> TFriendList;
private:
    FriendList* m_friendList;

функция сохранения

QString path = "/friendlist.bin";
QFile file(path);

if (file.open(QIODevice::WriteOnly))
{
    QDataStream out(&file);
    out << m_friendList;
    file.close();
}

функция загрузки

QString path = "/friendlist.bin";
QFile file(path);
if(file.exists())
{
  if (file.open(QIODevice::ReadOnly))
  {
     QDataStream in(&file);
     in >> m_friendList;
     file.close();
     qDebug() << "FriendList.size() = " << m_friendList->size();
     }
}

Это сохраняет файл в нужном направлении, но, к сожалению, загрузка дает мне пустой список размером 0. Это где я застрял..

Кто-нибудь может помочь?

3 ответа

Решение

Из вашего кода, чтобы перестроить список:

for(int i = 0; i < list->size(); i++) 

Проблема в том, что когда вы десериализуетесь в пустой список size() вернет 0 (или значение, совершенно не связанное с тем, что вы должны прочитать с диска), и в любом случае вам придется читать элементы из потока, это не имеет значения для фактического размера списка. Кроме того, список пуст, поэтому вы должны сначала создать новый элемент (вы не можете просто вызвать at() потому что внутри нет элементов). Вы можете написать целое число (например) перед элементами, а затем прочитать его при десериализации:

QDataStream &operator>>(QDataStream& in, FriendList* list)
{
    int count = 0;
    in >> count;

    for(int i = 0; i < count; i++)
    {
        ContactData* contact = new ContactData();
        in >> contact;

        list->m_list->push_back(contact);
    }

    return in;
}

Не забудь написать count в функции сериализации тоже. В качестве альтернативы вы можете прочитать все до конца входного потока:

QDataStream &operator>>(QDataStream& in, FriendList* list)
{
    int count = 0;
    in >> count;

    while (!in.atEnd())
    {
        ContactData* contact = new ContactData();
        in >> contact;

        list->m_list->push_back(contact);
    }

    return in;
}

Чтобы закончить, проверьте, что сказал Камиль в комментарии, если у вас нет ошибок во время сериализации, возможно, это просто опечатка, но...

Вам не нужно перегружать >> а также << операторы для QListони уже существуют, когда левый оператор QDataStream

см документацию

Поскольку отдельный объект может сериализоваться и десериализоваться правильно, все контейнеры Qt также должны сериализоваться и десериализоваться.

Спасибо всем, кто предоставил помощь, теперь она отлично работает для меня. Для тех, кто заинтересован, вот что мне пришлось изменить:

функция сохранения

if (file.open(QIODevice::WriteOnly))
{
    QDataStream out(&file);
    out << *m_friendList;
    file.close();
}

friendlist.cpp

QDataStream &operator>>(QDataStream& in, FriendList* list)
{
    while (!in.atEnd())
    {
        ContactData* contact = new ContactData();
        in >> contact;
        list->m_list->push_back(contact);
    }
    return in;
}
Другие вопросы по тегам