Страницы

Поиск по вопросам

четверг, 26 декабря 2019 г.

Qt. Как сериализовать объекты содержащие коллекции?

#cpp #qt #сериализация


Имеются вот такие вот классы:

class Institution //Класс "учебное заведение"
{
    ...
private:
    ...
    QList Pupils; //Коллекция учеников
};

class Pupil //Класс "ученик"
{
    ...
private:
    ...
    QList Lessons; //Коллекция предметов
};

class Exam //Класс "экзамен"
{
    ...
};


Необходимо сериализовать коллекцию объектов класса Institution (хотя я не уверен
уместно ли называть это сериализацией), а именно сохранить это коллекцию в бинарник
и потом "взять" её оттуда.

Сохранение (здесь проблем нет, т.е. sizeof работает как надо):

QList institutions;
...
Institution bf("", 0);
char str[1024];
strcpy(str, filename.toStdString().c_str());
std::ofstream out(str, std::ios::out | std::ios::binary);
for (int i = 0; i < institutions.size(); i++)
{
    bf = *institutions[i];
    int a = sizeof bf;
    out.write((char *) &bf, sizeof bf);
}
out.close();


Считывание (здесь, понятное дело, sizeof не работает, т.к. размер вложенных коллекций
заранее не определить):

QList institutions;
...
institutions.clear();
char str[1024];
strcpy(str, filename.toStdString().c_str());
std::ifstream in(str, std::ios::in | std::ios::binary);
while (!in.eof() && in.peek() != EOF)
{
    Institution *bf = new Institution("", 0);
    int a = sizeof bf;
    in.read((char *) bf, sizeof *bf); //!
    institutions.append(bf);
}
in.close();


Теперь и вопрос, как всё-таки можно записать и считать эту коллекцию в/из бинарника,
не изменяя структуру классов(!)?

Или может быть есть что-то подобное как в Java?

/*Коллекция*/
ArrayList list = new ArrayList();
/*Запись*/
try
{
    FileOutputStream fos = new FileOutputStream(file.toString());
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(list);
    oos.close();
    fos.close();
}
catch(IOException ioe)
{
}

/*Считывание*/
FileInputStream fis = new FileInputStream(file.toString());
ObjectInputStream ois = new ObjectInputStream(fis);
try
{
    list = (ArrayList) ois.readObject();
} 
catch (ClassNotFoundException e)
{
}
ois.close();
fis.close();


UPD#1:
Всё решилось использованием QDataStream, заменой всех коллекций с указателями на
объекты классов на коллекции с объектами классов и перегрузкой operator <<, operator
>> для QDataStream:

QDataStream &operator << (QDataStream &out, const Institution &s);
QDataStream &operator >> (QDataStream &in, Institution &s);
QDataStream &operator << (QDataStream &out, const Pupil &s);
QDataStream &operator >> (QDataStream &in, Pupil &s);
QDataStream &operator << (QDataStream &out, const Exam &s);
QDataStream &operator >> (QDataStream &in, Exam &s);


Пример реализации:

QDataStream &operator << (QDataStream &out, const Institution &s)
{
    out << s.getName() << s.getID() << s.getPupils();
    return out;
}

QDataStream &operator >> (QDataStream &in, Institution &s)
{
    QString Name;
    int ID;
    QList Pupils;
    in >> Name >> ID >> Pupils;
    s = Institution(Name, ID, Pupils);
    return in;
}

    


Ответы

Ответ 1



Всё решилось использованием QDataStream, заменой всех коллекций с указателями на объекты классов на коллекции с объектами классов и перегрузкой operator <<, operator >> для QDataStream: QDataStream &operator << (QDataStream &out, const Institution &s); QDataStream &operator >> (QDataStream &in, Institution &s); QDataStream &operator << (QDataStream &out, const Pupil &s); QDataStream &operator >> (QDataStream &in, Pupil &s); QDataStream &operator << (QDataStream &out, const Exam &s); QDataStream &operator >> (QDataStream &in, Exam &s); Пример реализации: QDataStream &operator << (QDataStream &out, const Institution &s) { out << s.getName() << s.getID() << s.getPupils(); return out; } QDataStream &operator >> (QDataStream &in, Institution &s) { QString Name; int ID; QList Pupils; in >> Name >> ID >> Pupils; s = Institution(Name, ID, Pupils); return in; }

Комментариев нет:

Отправить комментарий