我们有时候会有这样的需求场景,需要将一个对象以二进制形式保存在文件或者字符流中,以便下一次加载时可以直接从二进制文件或者流中直接读取对象,并对对象进行操作。
对象存储的目的,本质是要存储对象中各个成员的数据。因此我们从两个角度来思考这个问题。
1、对象在实例化后,会为其分配一片内存空间,在这片内存空间上会记录各个成员变量的值。因此,我们会首先想到直接进行内存拷贝,保存对象的二进制数据。
2、序列化的方式分别保存对象中各个成员变量的值,并在反序列化的过程中对对象的各个成员变量分别赋值。
下面记录简单的演示方法:
#include <QCoreApplication>
#include <QDataStream>
#include <QTextStream>
#include <QFile>
#include <QDebug>
#include <iostream>
#include <fstream>
#include <sstream>
#include <QDataStream>
using namespace std;
class BinData
{
public:
BinData(){}
BinData(QString name,int age):m_name(name),m_age(age) {}
QString name(){ return m_name;}
int age(){ return m_age;}
public:
QString m_name;
int m_age;
};
QDataStream& operator <<(QDataStream& s,const BinData& that)
{
s << that.m_name << that.m_age;
return s;
}
void operator >> (QDataStream& s,BinData& that)
{
s >> that.m_name >> that.m_age;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BinData dt(QStringLiteral("张山"),20);
/// [1] ------------------------------------
/// 将对象以二进制形式保存到文件
ofstream ofs("binObject",std::ios::binary);
ofs.write((char*)&dt,sizeof(dt));
ofs.close();
/// 从二进制文件中反序列化对象
BinData rdt;
ifstream ifs("binObject",std::ios::binary);
ifs.read((char*)&rdt,sizeof(rdt));
ifs.close();
qDebug() << rdt.name() << rdt.age() << Qt::endl;
/// [2] ------------------------------------
/// 将对象序列化为二进制字符串
stringstream s(std::ios::in | std::ios::binary);
s.read((char*)&dt,sizeof(dt));
/// 从stringstream中读取BinData对象
BinData srdt;
s.write((char*)&srdt,sizeof(rdt));
qDebug() << rdt.name() << rdt.age() << Qt::endl;
/// [3] ------------------------------------
/// 使用QDataStream 实现的序列化
QFile qf("qbinObject");
qf.open(QIODevice::WriteOnly);
QDataStream qds(&qf);
qds << dt;
qf.close();
/// 使用QDataStream 实现的反序列化
BinData qrdt;
qf.open(QIODevice::ReadOnly);
QDataStream qrds(&qf);
qrds >> qrdt;
qf.close();
qDebug() << qrdt.name() << qrdt.age() << Qt::endl;
return a.exec();
}
输出结果如下: