Russian Qt Forum

Qt => Работа с сетью => Тема начата: deaks от Июнь 14, 2011, 11:38



Название: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 11:38
Здравствуйте,

как сделать данный сабж?

прошу не пинать ногами. лучше посоветовать-подсказать или дать ссылку на внятный пример.
спасибо=)

PS в частности интересует, как запаковать QVector<мой объект>


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 11:43
можно ли обойтись связкой QDataStream и QByteArray?


Название: Re: Сериализация объектов
Отправлено: asvil от Июнь 14, 2011, 11:46
да


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 12:08
так будет верно?

На отправляющей стороне
Код
C++ (Qt)
QByteArray ba;
QDataStream ds1(&ba, QIODevice::WriteOnly);
QVector<object> objects1;
ds1 << objects2;
 

На принимающей стороне
Код
C++ (Qt)
QDataStream ds2(ba, QIODevice::ReadOnly);
QVector<object> objects2;
ds2.device()->reset();
ds2 >> objects2;
 


Название: Re: Сериализация объектов
Отправлено: RedDog от Июнь 14, 2011, 12:13
если свой объект не будет содержать в себе указатели на другие объекты и платформозависимые типы данных, тогда прокатит
хотя вряд ли вектор корректно передатся. лучше использовать простые типы/массивы


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 12:32
скорее всего такой вариант -

Код
C++ (Qt)
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
QVector<object> objects;
int size = objects->size();
ds << size;
for(int  i = 0; i < size; i++)
{
   ds << objects[i]->name;
   ds << objects[i]->angle;
   ds << objects[i]->velocity;
}    
[\code]
 
ну и на принимающей стороне все делать в обратном порядке с учетом считанного размера массива


Название: Re: Сериализация объектов
Отправлено: Igors от Июнь 14, 2011, 12:40
так будет верно?

На отправляющей стороне
...
Так "будет работать", но это не имеет отношения к сериализации :) Разница в том что у Вас точно известно какие типы читаются/пишутся, это фиксировано и не может быть изменено в runtime. Cериализация подразумевает что будут (автоматычно) созданы и прочитаны объекты того типа что записаны (а не Вы их создаете и затем читаете). Насколько мне известно, в Qt это делается через Q_DECLARE_METATYPE и затем QVariant. Хороший пример тоже хотел бы увидеть


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 13:35
Цитировать
Насколько мне известно, в Qt это делается через Q_DECLARE_METATYPE и затем QVariant. Хороший пример тоже хотел бы увидеть

может быть это - http://habrahabr.ru/blogs/qt_software/83374/ ?


Название: Re: Сериализация объектов
Отправлено: LisandreL от Июнь 14, 2011, 13:46
Так "будет работать", но это не имеет отношения к сериализации :) Разница в том что у Вас точно известно какие типы читаются/пишутся, это фиксировано и не может быть изменено в runtime. Cериализация подразумевает что будут (автоматычно) созданы и прочитаны объекты того типа что записаны
Ну на счёт не имеет отношения к сериализациии - это очень сильно сказанно. У троллей в Serializing Qt Data Types ровно такой же механизм описан. Определить по нему какой же тип был сериализован невозможно.


Насколько мне известно, в Qt это делается через Q_DECLARE_METATYPE и затем QVariant. Хороший пример тоже хотел бы увидеть
Увы, в Q_DECLARE_METATYPE нельзя указать MetaTypeID в итоге если данные будут передаваться не между идентичными исполняемыми файлам может получиться, что на разных сторонах один и тот же тип получит разный MetaTypeID ну а дальше кровь, кишки, распи…


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 15:34
так будет верно?

На отправляющей стороне
Код
C++ (Qt)
QByteArray ba;
QDataStream ds1(&ba, QIODevice::WriteOnly);
QVector<object> objects1;
ds1 << objects2;
 

На принимающей стороне
Код
C++ (Qt)
QDataStream ds2(ba, QIODevice::ReadOnly);
QVector<object> objects2;
ds2.device()->reset();
ds2 >> objects2;
 


так работать не будет! Надо как минимум реализовать функцию
Код:
QDataStream& operator<<(QDataStream& s, const object& v)
Также интересно что у тебя за обьекты, и можешь ли ты их хранить в контейнерах по значению.
 


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 15:35
..... Насколько мне известно, в Qt это делается через Q_DECLARE_METATYPE и затем QVariant. Хороший пример тоже хотел бы увидеть


http://cartan.cas.suffolk.edu/oopdocbook/opensource/exportcode.html (http://cartan.cas.suffolk.edu/oopdocbook/opensource/exportcode.html)


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 16:25
Цитировать

так работать не будет! Надо как минимум реализовать функцию
Код:
QDataStream& operator<<(QDataStream& s, const object& v)
Также интересно что у тебя за обьекты, и можешь ли ты их хранить в контейнерах по значению.
 

вместо этого, в классе реализовал метод сериализации (десериализации) возвращающий (принимающий) QByteArray c записанными полями объекта
то есть так:

Код
C++ (Qt)
bool ShmObject::serialize(QByteArray &ba)
{
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << name;
ds << shape;
ds << psi;
return true;
}
 

где name, shape, psi - поля класса. в результате в ba будут лежать требуемые данные.

так верно?


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 16:45
так верно?

Твой код сериализации обьекта с таким:
Код
C++ (Qt)
QDataStream ds1(&ba, QIODevice::WriteOnly);
QVector<object> objects1;
ds1 << objects2;
работать не будет.
Потому что при сериализации вектора вызывается
Код:
operator<<()
для каждого элемента вектора.


P.S. может попробуй описать задачу поподробней (какие обьекты, от чего наследуются, как хранятся).

Mожет boost::serialization? (http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/index.html)


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 16:49
Цитировать

Твой код сериализации обьекта с таким:
Код
C++ (Qt)
QDataStream ds1(&ba, QIODevice::WriteOnly);
QVector<object> objects1;
ds1 << objects2;
работать не будет.
Потому что при сериализации вектора вызывается
Код:
operator<<()
для каждого элемента вектора.


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

в целом-то подход правильный?


Название: Re: Сериализация объектов
Отправлено: Igors от Июнь 14, 2011, 16:54
может быть это - http://habrahabr.ru/blogs/qt_software/83374/ ?
Хмм... ну не знаю. Автор пишет
Цитировать
Ведь C++ и так предоставляет достаточно гибкие возможности при сериализации в поток.
Это какие же? Мне известен аж один, выглядит так
Код
C++ (Qt)
int ID = stream.ReadInt();
switch (ID) {
  case ID_OBJ1:
  {
    MyObj1 * obj1 = new MyObj1();
    obj1->Read(stream);
    this->SetData1(obj1);
    break;
  }  
  // и еще столько case сколько типов объектов
 ...
}
 
Запихнуть все подлежащее записи в properties - идея понятна, но на мой взгляд, выигрыша особого не видно. Немного отбили на ручном разборе ID - зато теперь надо как-то держать QVariant/property.

Во всем этом есть малозаметная вещь которая, однако, по сложности превышает в десятки раз обсуждаемое. Написать "сериализацию" в первый раз очень легко. Но вот когда формат данных изменился (что-то отжило, новое добавилось) - вот тут наступает звериный кайф. Выясняется, что старые структуры просто так не снести - файлы перестанут читаться. Поэтому первое что мне бросилось в глаза - автор статьи не пишет число properties в поток - ну наверное у него ничего меняться не будет  :)



Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 17:02

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

в целом-то подход правильный?

Я бы сказал:"Работать будет, но..."


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 17:06
Цитировать
P.S. может попробуй описать задачу поподробней (какие обьекты, от чего наследуются, как хранятся).

Mожет boost::serialization? (http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/index.html)

нет, буст мне тут не нужен.

передаваемые объекты имеют простую структуру. каждый имеет около десятка полей простых типов

PSSS

что-то не пойму, выполняю следующий код -
Код
C++ (Qt)
QByteArray ba;
       int count = 0;
QDataStream ds(&ba, QIODevice::WriteOnly);
 
ds << count;
 

так при этом у ba изменяется только поле size = 4, а поле data=""


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 17:12
Поэтому первое что мне бросилось в глаза - автор статьи не пишет число properties в поток - ну наверное у него ничего меняться не будет  :)

Автор получает количество свойств через
Код
C++ (Qt)
this->metaObject()->propertyCount()


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 17:16
так при этом у ba изменяется только поле size = 4, а поле data=""

Потому что поле data() имеет тип char*, т.е. сторка с завершающим нулем, а у тебя все 4 байта нули.


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 17:30
хмм, ну так-то да, но все равно, какое бы число я не передал в поток ba в поле data ничего не меняется

или это просто отладчик студии не хочет показывать?))


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 17:39
Код
C++ (Qt)
 
QString res;
for(int i = 0;i<ba.size();++i)
{
res.append(QString("%1").arg(static_cast<int>(data[i]),2,16,QChar('0')));
if(i<(data.size()-1))
{
res.append(' ');
}
}
qDebug()<<res;
 

Для отладки используй QtCreator2.2 (или старше ;)  )
И для кодинга тоже.


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 14, 2011, 17:51
хмм, и в самом деле отладчик студии не показывал...странно


Название: Re: Сериализация объектов
Отправлено: Igors от Июнь 14, 2011, 18:50
Автор получает количество свойств через
Код
C++ (Qt)
this->metaObject()->propertyCount()
А откуда уверенность что именно такое число пропердей сохранено в потоке? И именно таких что понимаются читающим? Никакой совместимостью здесь не пахнет


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 14, 2011, 19:12
А откуда уверенность что именно такое число пропердей сохранено в потоке? И именно таких что понимаются читающим? Никакой совместимостью здесь не пахнет
Ну есть небольшая надежда на то что вы серализуете QMySeriazableClass, а потом его и восстанавливаете. Вопрос, как определить что это именно QMySeriazableClass, а не QInheritedMySeriazableClassPlus2Prop в статье не рассмотрен, его надо решать. Надо как-то сохранять информацию о типе, а затем при чтении создавать обьекты нужного типа. посмотрите ссылку, которую я давал раньше http://cartan.cas.suffolk.edu/oopdocbook/opensource/exportcode.html


Название: Re: Сериализация объектов
Отправлено: Igors от Июнь 15, 2011, 15:38
Надо как-то сохранять информацию о типе, а затем при чтении создавать обьекты нужного типа. посмотрите ссылку, которую я давал раньше http://cartan.cas.suffolk.edu/oopdocbook/opensource/exportcode.html
Ну рекурсивно сохранили все дерево, с экспорта (пишущего) много не возьмешь, он пишет что у него есть. А вот с читающим - др. дело. Хотелось бы чтобы он сам создавал объекты из потока, не заставляя меня разбираться с оbjectName и.т.п. Хотя возможно я слишком много хочу и оптимальный подход - крутить самому используя механизм properties (если я правильно понял их надо выгружать/загружать в рабочие данные).


Название: Re: Сериализация объектов
Отправлено: deaks от Июнь 15, 2011, 15:51
Код
C++ (Qt)
 
QString res;
for(int i = 0;i<ba.size();++i)
{
res.append(QString("%1").arg(static_cast<int>(data[i]),2,16,QChar('0')));
if(i<(data.size()-1))
{
res.append(' ');
}
}
qDebug()<<res;
 

Для отладки используй QtCreator2.2 (или старше ;)  )
И для кодинга тоже.

выполнил все так. res содержит данные.
хочу скопировать данные массива в строку(char *):
Код
C++ (Qt)
strcpy(outData, ba.constData());
 
но в результате пустая строка. видимо я чего-то не понимаю


Название: Re: Сериализация объектов
Отправлено: kambala от Июнь 15, 2011, 16:19
так если данные находятся в res, зачем копируешь из ba?
Код
C++ (Qt)
strcpy(outData, res.toLatin1().constData());
или я тоже чего-то не понимаю? :)


Название: Re: Сериализация объектов
Отправлено: alex312 от Июнь 15, 2011, 18:10
to deaks Блин, у тебя же бинарные данные, вот обьясни, ну навига тебе этот допотопный char*  ???

to kambala Даные таки находятся в ba, а res  - так для отладки перевод бинарных данных в строковое представление (для отладки).