Russian Qt Forum

Qt => Общие вопросы => Тема начата: JamS007 от Январь 05, 2010, 19:08



Название: [Решено] Как сохранить контейнерный класс на диск?
Отправлено: JamS007 от Январь 05, 2010, 19:08
Здравствуйте,

в своей программе работаю с несколькими контейнерными классами, такими как: QList, QHash, QMultiHash. А тут мне понадобилась возможность сохранять эти контейнеры на диск с возможностью их последующего восстановления. Подскажите, пожалуйста, как правильно это сделать, может есть уже какой-нибудь проверенный метод, чтоб не изобретать велосипед?

спасибо.


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: BRE от Январь 05, 2010, 19:10
Посмотри на QDataStream.


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: JamS007 от Январь 05, 2010, 19:13
смотрел... может я что-то неправильно делаю, но ничего не сохраняется (как мне кажется) вот код:

Код:
QFile file(path + fileName + databaseFormat);
    if (file.open(QIODevice::WriteOnly))
    {
        QDataStream stream(&file);
        stream.setVersion(QDataStream::Qt_4_6);
        stream << studentsList // QList<QString>
               << marksList //QMultiHash<QString, QHash<int,char> >
               << themes //QHash<QString>
               << remind //QHash<QString>
               << materials; //QHash<QString>
        if (stream.status() == QDataStream::Ok) return true;
    }
    //отправить отчет в ErrorStack

    // ...
    #ifdef QT_DEBUG
    qDebug() << "DataModel::saveDatabase - error";
    #endif
    return false;


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: lit-uriy от Январь 05, 2010, 19:18
>>но ничего не сохраняется (как мне кажется)
ну ты файл открой текстовом редакторе и посмотри, есть там что-нибудь или нет.
Ну и попробуй программно загрузить


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: JamS007 от Январь 05, 2010, 19:23
Именно так и делаю. При каждом открытии файла там оказывается только 5 нечитаемых символов. причём это не зависит от количества записей в контейнере, будь их хоть 100, там все равно окажется 5 нечитаемых символов. А размер файла всегда равен 1 кб.


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: niXman от Январь 05, 2010, 19:26
http://www.boost.org/doc/libs/1_41_0/libs/serialization/doc/index.html


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: BRE от Январь 05, 2010, 19:33
Именно так и делаю. При каждом открытии файла там оказывается только 5 нечитаемых символов. причём это не зависит от количества записей в контейнере, будь их хоть 100, там все равно окажется 5 нечитаемых символов. А размер файла всегда равен 1 кб.
Интересно, 5 не читаемых символов размером в 1 Кб. Попробуй прочитать этот файл с использованием QDataStream, станет ясно сохраняется что-то или нет.
Коллекции сохраняются в бинарном формате, читать их как текст вряд-ли получиться.


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: lit-uriy от Январь 05, 2010, 20:00
всё должно быть нормально, вот тест:
Код
C++ (Qt)
#include <QtGui>
 
int main(int argc, char* argv[])
{
{
QList<QString> stringList;
QList<int> intList;
stringList << "one" << "two";
intList << 1 << 2;
QFile f("./out.bin");
if (f.open(QIODevice::WriteOnly)){
QDataStream stream(&f);
stream << stringList
 << intList;
if (stream.status() != QDataStream::Ok){
qDebug() << "Write error";
return 1;
}else{
qDebug() << "Write successfully complete";
}
}else{
qDebug() << "Unable to open file";
return 1;
}
}
 
// -------------------
{
QList<QString> stringList;
QList<int> intList;
QFile f("./out.bin");
if (f.open(QIODevice::ReadOnly)){
QDataStream stream(&f);
stream >> stringList
 >> intList;
if (stream.status() != QDataStream::Ok){
qDebug() << "Read error";
return 1;
}
qDebug() << "-------";
qDebug() << "stringList:\n" << stringList;
qDebug() << "intList:\n" << intList;
}else{
qDebug() << "Unable to open file";
return 1;
}
}
   return 0;
}
 
 
 


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: JamS007 от Январь 05, 2010, 20:10
Мда... похоже надо будет выдумать велосипед, так как:

Цитата: from assistant
Reading and writing other Qt classes.

In addition to the overloaded stream operators documented here, any Qt classes that you might want to serialize to a QDataStream will have appropriate stream operators declared as non-member of the class:

 QDataStream &operator<<(QDataStream &, const QXxx &);
 QDataStream &operator>>(QDataStream &, QXxx &);
For example, here are the stream operators declared as non-members of the QImage class:

 QDataStream & operator<< (QDataStream& stream, const QImage& image);
 QDataStream & operator>> (QDataStream& stream, QImage& image);
To see if your favorite Qt class has similar stream operators defined, check the Related Non-Members section of the class's documentation page.

2 lit-uriy: у класса QList<T> есть Related Non-Members
Цитировать
QDataStream & operator<< ( QDataStream & out, const QList<T> & list )
QDataStream & operator>> ( QDataStream & in, QList<T> & list )

а класса QHash<K,T> их нету. И соответственно, готового оператора для записи через QDataStream нету. :(


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: uriel от Январь 05, 2010, 20:13
А как тогда Ваш первый пример вообще скомпилировался? :)
Всё есть.
Цитировать
QDataStream &   operator<< ( QDataStream & out, const QHash<Key, T> & hash )
QDataStream &   operator>> ( QDataStream & in, QHash<Key, T> & hash )


Название: Re: Как сохранить контейнерный класс на диск?
Отправлено: JamS007 от Январь 05, 2010, 20:17
да... действительно... сделал поспешный вывод.  Буду искать решение дальше.



Нашел решение. Дело в том, что если создавать и инициализировать контейнерные классы динамически
Код:
 QMultiHash<QString, QHash<unsigned int, unsigned char> > *marksList;
//...
marksList    = new QMultiHash<QString, QHash<unsigned int, unsigned char> >();

то при сохранении на диск нужно использовать оператор <*> перед указателем, пример

Код:
QDataStream stream(&file);
        stream.setVersion(QDataStream::Qt_4_6);
        stream << *marksList;

а если передавать сам указатель или разыменованый указатель (&), то на диск сохраниться как раз таки указатель... (Если я правильно понял)