QT数据序列化转载及修正----我们考虑的内容科学家已经考虑过了
2014-12-12 17:11
267 查看
Qt中序列化数据的类是QDataStream,但这个类只能序列化基本类型和一部分Qt定义的类,对于自定义类需要自己编写序列化函数。
在自定义类中声明友元函数,并实现:
class CKDrawBase:
{
public:
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase);
friend QDataStream & operator >> (QDataStream &dataStream, CKDrawBase &drawBase);
}
很显然,一个用于流出,一个用于流入。
对于一个简单类的序列化重载两个操作符即可,对一个多态类象这样声明:
class CKDrawBase:public QObject
{
Q_OBJECT
public:
virtual void save(QDataStream &dataStream);
virtual void load(QDataStream &dataStream);
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase);
friend QDataStream & operator >> (QDataStream &dataStream, CKDrawBase **drawBase);
//其他的成员
};
虚函数save()和load()分别用于实际流入流出的实现,由重载操作符函数调用,这样子类就无须实现重载操作符函数,只须根据需要重载save()和load()即可。
子类如下声明:
class CKDrawLine : public CKDrawBase
{
Q_OBJECT
public:
void save(QDataStream &dataStream);
void load(QDataStream &dataStream);
//其他的成员
};
class CKDrawRectangle:public CKDrawBase
{
Q_OBJECT
public:
void save(QDataStream &dataStream);
void load(QDataStream &dataStream);
//其他的成员
};
重载<<函数实现:
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase)
{
dataStream << QString(drawBase.metaObject()->className());//将对象的类名写入流中
drawBase.save(dataStream);
return dataStream;
}
在函数中,首先将对象的类名写入流中,然后调入save()函数,实现具体的数据流入。
重载>>函数实现:
QDataStream & operator >> (QDataStream &dataStream, CKDrawBase **drawBase)
{
QString str;
dataStream >> str;
*drawBase = NULL;
if (str == QString("CKDrawLine")) //根据类名字符串生成相应类的对象
{
*drawBase = new CKDrawLine;
(*drawBase)->load(dataStream);
return dataStream;
}
if (str == QString("CKDrawRectangle"))
{
*drawBase = new CKDrawRectangle;
(*drawBase)->load(dataStream);
return dataStream;
}
return dataStream;
}
在函数中,先读出保存的类名,然后根据相应的类名生成相应的对象,生成的对象指针保存在*drawBase中。
使用:
上述程序编写好后,就可以使用了。
例:
声明了一个QList对象QList drawList,要将其保存到文件中,或从文件中读出:
保存:
dataStream << drawList.count(); // dataStream为QdataStream类型。
QList::const_iterator i;
for (i=drawList.constBegin();i!=drawList.constEnd();++i)
{
dataStream << *(*i);
}
读出:
int count;
CKDrawBase *ptr;
dataStream >> count; // dataStream为QdataStream类型。
for (int i=0; i {
dataStream >> &ptr;
if (ptr != NULL)
{
drawList.append(ptr);
}
}
说明:
1、使用多态的话,必须要从QObject继承,因为要保存类名字符串。
2、每增加一个子类,都要修改重载>>函数实现,以生成相应的对象。
3、还不知道有没有更好的办法;
补充:更好的办法就是依照qt的规则声明宏和实现宏。
在自定义类中声明友元函数,并实现:
class CKDrawBase:
{
public:
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase);
friend QDataStream & operator >> (QDataStream &dataStream, CKDrawBase &drawBase);
}
很显然,一个用于流出,一个用于流入。
对于一个简单类的序列化重载两个操作符即可,对一个多态类象这样声明:
class CKDrawBase:public QObject
{
Q_OBJECT
public:
virtual void save(QDataStream &dataStream);
virtual void load(QDataStream &dataStream);
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase);
friend QDataStream & operator >> (QDataStream &dataStream, CKDrawBase **drawBase);
//其他的成员
};
虚函数save()和load()分别用于实际流入流出的实现,由重载操作符函数调用,这样子类就无须实现重载操作符函数,只须根据需要重载save()和load()即可。
子类如下声明:
class CKDrawLine : public CKDrawBase
{
Q_OBJECT
public:
void save(QDataStream &dataStream);
void load(QDataStream &dataStream);
//其他的成员
};
class CKDrawRectangle:public CKDrawBase
{
Q_OBJECT
public:
void save(QDataStream &dataStream);
void load(QDataStream &dataStream);
//其他的成员
};
重载<<函数实现:
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase)
{
dataStream << QString(drawBase.metaObject()->className());//将对象的类名写入流中
drawBase.save(dataStream);
return dataStream;
}
在函数中,首先将对象的类名写入流中,然后调入save()函数,实现具体的数据流入。
重载>>函数实现:
QDataStream & operator >> (QDataStream &dataStream, CKDrawBase **drawBase)
{
QString str;
dataStream >> str;
*drawBase = NULL;
if (str == QString("CKDrawLine")) //根据类名字符串生成相应类的对象
{
*drawBase = new CKDrawLine;
(*drawBase)->load(dataStream);
return dataStream;
}
if (str == QString("CKDrawRectangle"))
{
*drawBase = new CKDrawRectangle;
(*drawBase)->load(dataStream);
return dataStream;
}
return dataStream;
}
在函数中,先读出保存的类名,然后根据相应的类名生成相应的对象,生成的对象指针保存在*drawBase中。
使用:
上述程序编写好后,就可以使用了。
例:
声明了一个QList对象QList drawList,要将其保存到文件中,或从文件中读出:
保存:
dataStream << drawList.count(); // dataStream为QdataStream类型。
QList::const_iterator i;
for (i=drawList.constBegin();i!=drawList.constEnd();++i)
{
dataStream << *(*i);
}
读出:
int count;
CKDrawBase *ptr;
dataStream >> count; // dataStream为QdataStream类型。
for (int i=0; i {
dataStream >> &ptr;
if (ptr != NULL)
{
drawList.append(ptr);
}
}
说明:
1、使用多态的话,必须要从QObject继承,因为要保存类名字符串。
2、每增加一个子类,都要修改重载>>函数实现,以生成相应的对象。
3、还不知道有没有更好的办法;
补充:更好的办法就是依照qt的规则声明宏和实现宏。
相关文章推荐
- ASP.NET AJAX客户端编程之旅(三)——让JavaScript和C#无障碍沟通:数据类型自动转换&序列化(转载)
- ArcEngine中对已经存在的数据表格添加字段(转载)
- 与美国数据科学家对话:大数据如何影响我们的生活?
- 基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据
- Qt开发,链接了数据库后,调用QSqlQuery::setQuery执行SQL语句获取我们想要的数据
- 网站相争 搜索得利:诙谐地说,门户网站已经沦为内容打工者(转载)
- 【C#】解决进行反序列化时出错:。InnerException 消息是“反序列化对象 属于类型 System.String 时出现错误。读取 XML 数据时,超出最大字符串内容长度配额 (8192)。
- 这些行业已经开始用数据挖掘了,我们的前途光明
- 【转载】IT屌丝如何成为数据科学家?
- 【MINA】序列化和反序列化我们要考虑的问题
- QT线程共享数据(转载)
- 从数据库中读取出的数据如何在GridView显示成我们所需要的内容?
- Android 内容提供器---创建内容提供器(数据设计考虑因素)
- Extjs4 Grid内容已经拿到但是不显示数据
- InnerException 消息是“反序列化对象 属于类型 *** 时出现错误。读取 XML 数据时,超出最大字符串内容长度配额 (8192)。(注意细节)
- WCF学习笔记(四):转载MSDN,数据协定序列化程序支持的类型
- (转载)SQL 2005 当我们想将某个字段相同的几行数据合并为一列显示的时候 合并列值
- Oracle 10g数据库中,当在数据库中创建用户时,基于应用性能和管理方面的考虑,最好为不同的用户创建独立的表空间。 那么创建表空间的步骤是怎样实现的呢?本文我们主要就介绍了这一部分内容,接下来就让
- unity3d,序列化将数据类的内容生成为XML配置
- QT数据传输中的对象序列化与反序列化