cpp类序列化输出

说明

在软件开发中,经常需要将整个类数据持久化,比如将配置类中的成员数据保存到配置文件,又或是对一些场景数据进行导出导入,这个时候就需要一个数据转换,如下图:
在这里插入图片描述

思路

1、使用数据流方式输出到文件。
考虑到类的类型不确定性,所以我们需要使用模板参数传入,然后将模板转为数据流。
2、从类到文件,我们分两步,先将类模板转为 hex类型,然后hex类型直接写入文件。
3、一般类不支持数据流操作,所以我们需要对我们的数据类实现操作符重载。

实现

实现代码参考QxOrm项目的序列化模块。

1 导出

类 到 hex数据:

template<class T>
inline QByteArray to_byte_array(const T &obj)
{
   QByteArray ba; QString err;
   QDataStream stream((& ba), QIODevice::WriteOnly);
   stream << (quint32)(9438);
	try { stream << obj; }
   catch (const std::exception & e) { err = QString("serialization error '%ERR%'").replace("%ERR%", e.what()); }
   catch (...) { err = QString("serialization error '%ERR%'").replace("%ERR%", "unknown error"); }
   if (! err.isEmpty()) { qDebug("to_byte_array() : %s", qPrintable(err)); ba.clear(); }
   return ba;
}

类 到 文件(使用到上面的函数)

template <class T>
inline bool to_file(const T & obj, const QString & sFileName)
{
    QByteArray data = to_byte_array(obj);
    QFile file(sFileName);
    if (! file.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return false;
    file.write(data);
    file.close();
    return true;
}

2 导入

hex数据 到 类

template <class T>
inline bool from_byte_array(T & obj, const QByteArray & data)
{
   bool result = false;
   if (data.isEmpty())
       return false;
   QDataStream stream(data);
   quint32 magic = 0;
   stream >> magic;
   if (magic != 9438)
       return false;
   stream >> obj;
   result = true;
   return result;
}

文件 到 类(使用到上面的函数)

template <class T>
inline bool from_file(T & obj, const QString & sFileName)
{
    QFile file(sFileName);
    if (! file.open(QIODevice::ReadOnly))
        return false;
    QByteArray data = file.readAll(); file.close();
    return from_byte_array(obj, data);
}

使用示例

1 数据对象设计

#include <QString>
#include <QByteArray>
#include <QDataStream>

//对象数据序列化模板类
class ExampleData
{
public:
    QString str1 = "";
    QString str2 = "";
    int i1 = 0;
    int i2 = 0;
    bool b1 = 0;
    bool b2 = 0;
    float f1 = 0.0;
    float f2 = 0.0;
    QByteArray hex1;
    QByteArray hex2;

    //一下两个操作符重载函数必须实现,否则无法输入输出数据流
    //下面重载操作符不可使得类不可继承QObject类(继承QObject后它不允许对象的赋值操作)
    friend QDataStream &operator<<(QDataStream &stream, const ExampleData &d)
    {
        stream << d.str1<<d.i1<<d.b1<<d.f1<<d.hex1;     //注意,该例子为导出变量1(实际为导出需要序列化输出保存的成员变量)
        return stream;
    }
    friend QDataStream &operator>>(QDataStream &stream, ExampleData &d)
    {
        stream >> d.str2>>d.i2>>d.b2>>d.f2>>d.hex2;     //注意,该例子为载入变量2(实际应与导出变量及其顺序保持一致)
        return stream;
    }
};

2 测试函数

#include "serialization.h"
#include <QVector>
#include <QDebug>
//序列化输出、输入测试函数
void testFunction()
{
    QVector<ExampleData> dataList;  //or QList、QMap、QHash
    for(int i = 0;i < 12;i ++)
    {
        ExampleData d;
        d.str1 = QString("string:%1").arg(i);
        d.i1 = qrand()%100;
        d.b1 = qrand()%2;
        d.f1 = (qrand()%100) / 0.1;
        d.hex1 = "123456789abcdefg";
        dataList.append(d);
    }
    Serialization::to_file(dataList,QString("./testFunctionFile"));
    dataList.clear();
    Serialization::from_file(dataList,QString("./testFunctionFile"));
    dataList.clear();
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值