声明:内容是老师PPT里的,非我原创 |
版本一:将一个类的一个对象序列化到文件
demo.h
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class demo{
private:
int i;
public:
demo(){
i=0;
}
demo(int j){
i=j;
}
//序列化方法
int Serialize(char* pBuffer){
long length=sizeof(this);
ofstream *o= new ofstream(pBuffer);
o->write((char*)this,length);
o->close();
delete o;
return 1;
}
//反序列化方法
static demo Deserialize(const char* pBuffer){
char buf[1000];
ifstream is(pBuffer);
is>>buf;
demo *a = (demo*)buf;
is.close();
return (*a);
}
void f(){
cout<<"i="<<this->i <<endl;
}
};
main.cpp
#include "demo.h"
int main(){
demo a(1);
a.Serialize("data");
demo b = demo::Deserialize("data");
b.f();
return 0;
}
运行示例:
执行main.cpp之后成功将demo类的实体a以二进制形式存入data文件中,并反序列化为实体b
版本二:将一个类的多个对象序列化到文件
思路:声明一个vector,循环序列化和反序列化
为什么要加#ifndef
这位网友说得很好
示例:
A.h
#ifndef _A_H_
#define _A_H_
#include <iostream>
#include <fstream>
#include <string>
using namespace std ;
class A{
private:
int i;
public:
A(){
i = 0;
}
A(int j){
i = j;
}
int Serialize(char* pBuffer){
long length = sizeof(this);
ofstream *o = new ofstream(pBuffer);
o->write((char*)this, length);
o->close();
delete o;
return 1;
}
static A Deserialize(const char* pBuffer){
char buf[1000];
ifstream is(pBuffer);
is >> buf;
A *a = (A*) buf;
is.close();
return (*a);
}
void f(){
cout << "i = " << this->i << endl;
}
int GetObjSize(unsigned int * pObjSize){
*pObjSize = 4;
return 1;
}
};
#endif
SerializerForAs.h
//
// Created by dj on 2018/10/26.
//
#include "A.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
using namespace std;
class SerializerForAs{
public:
static int Serialize(const char* pFilePath, vector<A *>& v){
FILE* fp = fopen(pFilePath, "w+");
for(int i = 0; i < v.size(); i++){
fwrite(v[i], sizeof(int), 1, fp);
}
fclose(fp);
return 1;
}
static int Deserialize(const char* pFilePath, vector<A *>& v){
FILE *fp = fopen(pFilePath, "r");
for(int i = 0; i < v.size(); i++){
fread(v[i], sizeof(int), 1, fp);
}
fclose(fp);
return 1;
}
};
main.cpp
#include "A.h"
#include <iostream>
#include <vector>
#include "SerializerForAs.h"
using namespace std;
int main(){
A a1(100);
A a2(200);
vector<A *> v1;
v1.push_back(&a1);
v1.push_back(&a2);
SerializerForAs::Serialize("data", v1);
A a3;
A a4;
vector<A *> v2;
v2.push_back(&a3);
v2.push_back(&a4);
SerializerForAs::Deserialize("data", v2);
a3.f();
a4.f();
}
版本三:将两个不同类的多个对象序列化到文件
思路:对象变成的字节流中,要有能够识别对象类型的信息
把一个类的对象和一个用来区别类种类的int字段封装在一个结构体内。
#include <iostream>
#include <stdio.h>
#include <fcntl.h>
#include <vector>
using namespace std;
class A{
public:
A(){
i = 0;
}
A(int j){
i = j;
}
void f(){
cout << "i = " << i << endl;
}
public:
bool Serialize(FILE *fp){
if(fp == NULL)
return false;
fwrite(&i, sizeof(int), 1, fp);
return true;
}
bool Deserialize(FILE *fp){
if(fp == NULL)
return false;
fread(this, sizeof(int), 1, fp);
return true;
}
private:
int i;
};
class B{
public:
B(){
i = 0;
j = 0;
}
B(int k){
i = k;
j = k + 1;
}
bool Serialize(FILE* fp){
if(fp == NULL)
return false;
fwrite(&i, sizeof(int), 1, fp);
fwrite(&j, sizeof(int), 1, fp);
return true;
}
bool Deserialize(FILE* fp){
fread(&(this->i), sizeof(int), 1, fp);
fread(&(this->j), sizeof(int), 1, fp);
return true;
}
void f(){
cout << "i = " << i << " , j = " << j << endl;
}
private:
int i, j;
};
struct Serialized{
int nType;
void *pObj;
};
class Serializer{
public:
bool Serialize(const char* pFilePath, vector<Serialized>& v){
FILE* fp = fopen(pFilePath, "w+");
if(fp == NULL)
return false;
for(int i = 0; i < v.size(); i++){
fwrite(&(v[i].nType), sizeof(int), 1, fp);
if(0 == v[i].nType){
A *p = (A*)(v[i].pObj);
p->Serialize(fp);
}else if(1 == v[i].nType){
B *p = (B*)(v[i].pObj);
p->Serialize(fp);
}
}
fclose(fp);
}
bool Deserialize(const char *pFilePath, vector<Serialized> &v){
FILE* fp = fopen(pFilePath, "r+");
for(;;){
int nType;
int r = fread(&nType, sizeof(int), 1, fp);
if(-1 == r || 0 == r)
break;
if(0 == nType){
A *p;
p = new A();
p->Deserialize(fp);
Serialized s;
s.nType = nType;
s.pObj = p;
v.push_back(s);
}else if(1 == nType){
B *p;
p = new B();
p -> Deserialize(fp);
Serialized s;
s.nType = nType;
s.pObj = p;
v.push_back(s);
}
}
fclose(fp);
return true;
}
};
int main() {
{
{
A a1(2);
Serialized s1;
s1.nType = 0;
s1.pObj = &a1;
B b1(3);
Serialized s2;
s2.nType = 1;
s2.pObj = &b1;
B b2(4);
Serialized s3;
s3.nType = 1;
s3.pObj = &b2;
A a2(5);
Serialized s4;
s4.nType = 0;
s4.pObj = &a2;
vector<Serialized> v;
v.push_back(s1);
v.push_back(s2);
v.push_back(s3);
v.push_back(s4);
Serializer s;
s.Serialize("data", v);
}
{
Serializer s;
vector<Serialized> v;
s.Deserialize("data", v);
for(int i = 0; i < v.size(); i++){
if(v[i].nType == 0){
A *p = (A*)(v[i].pObj);
p->f();
}else if(v[i].nType == 1){
B *p = (B*)(v[i].pObj);
p->f();
}
}
}
return 0;
}
}
版本四:将三个不同类的多个对象序列化到文件
要求:当又有新的类的对象,需要序列化到文件时,不能修改已有的代码
采用面向对象的方法,查找变化点,抽象出需要进行序列化的基类
思路:申明一个接口,每一个需要序列化的对象都是接口的实现
#include <fcntl.h>
#include <iostream>
#include <vector>
#include <stdio.h>
class ILSerializable
{
public:
virtual bool Serialize(FILE* fp) = 0;
virtual ILSerializable* Deserialize(FILE* fp) = 0;
virtual bool GetType(int& type) = 0;
public:
ILSerializable()
{
}
virtual ~ILSerializable()
{
}
};
class A : public ILSerializable
{
public:
A()
{
i = 0;
}
explicit A(int j)
{
i = j;
}
virtual ~A()
{
}
public:
void f()
{
std::cout << "in f(): " << i << std::endl;
}
public:
virtual bool GetType(int& type)
{
type = 0;
return true;
}
virtual bool Serialize(FILE *fp){
if(fp == NULL)
return false;
fwrite(&i, sizeof(int), 1, fp);
return true;
}
virtual ILSerializable* Deserialize(FILE *fp){
A *p = new A();
fread(&(p->i), sizeof(int), 1, fp);
return p;
}
private:
int i;
};
class B : public ILSerializable
{
public:
B()
{
i = 0;
j = 0;
}
explicit B(int k)
{
i = k;
j = k + 1;
}
virtual ~B()
{
}
public:
void f()
{
std::cout << "in f(): " << i << " " << j << std::endl;
}
public:
virtual bool GetType(int& type)
{
type = 1;
return true;
}
virtual bool Serialize(FILE *fp)
{
if(fp == NULL)
return false;
fwrite(&i, sizeof(int), 1, fp);
fwrite(&j, sizeof(int), 1, fp);
return true;
}
virtual ILSerializable* Deserialize(FILE* fp)
{
B *p = new B();
fread(&(p->i), sizeof(int), 1, fp);
fread(&(p->j), sizeof(int), 1, fp);
return p;
}
private:
int i;
int j;
};
class CLSerializer
{
public:
bool Serialize(const char *pFilePath, std::vector<ILSerializable*>& v)
{
FILE* fp = fopen(pFilePath, "w+");
if(fp == NULL)
return false;
for(int i = 0; i < v.size(); i++)
{
int type;
v[i]->GetType(type);
fwrite(&type, sizeof(int), 1, fp);
v[i]->Serialize(fp);
}
fclose(fp);
return true;
}
bool Deserialize(const char *pFilePath, std::vector<ILSerializable*>& v)
{
FILE* fp = fopen(pFilePath, "r+");
if(fp == NULL)
return false;
for(;;)
{
int nType = -1;
int r = fread(&nType, sizeof(int), 1, fp);
int type;
for(int i = 0; i < m_vSerialized.size(); i++)
{
m_vSerialized[i]->GetType(type);
if(type == nType)
{
ILSerializable *p = m_vSerialized[i]->Deserialize(fp);
if(p != NULL)
v.push_back(p);
}
}
if(r == 0)
break;
}
fclose(fp);
return true;
}
void Register(ILSerializable *pSerialized)
{
m_vSerialized.push_back(pSerialized);
}
private:
std::vector<ILSerializable*> m_vSerialized;
};
int main()
{
{
A a1(2);
B b1(3);
B b2(4);
A a2(5);
std::vector<ILSerializable*> v;
v.push_back(&a1);
v.push_back(&b1);
v.push_back(&b2);
v.push_back(&a2);
CLSerializer s;
s.Serialize("data", v);
}
{
CLSerializer s;
A a;
B b;
s.Register(&a);
s.Register(&b);
std::vector<ILSerializable*> v;
s.Deserialize("data", v);
for(int i = 0; i < v.size(); i++)
{
A *p = dynamic_cast<A *>(v[i]);
if(p != NULL)
p->f();
B *q = dynamic_cast<B *>(v[i]);
if(q != NULL)
q->f();
}
}
return 0;
}
版本五:配置序列化位置
读取配置文件写的序列化路径,在config.txt里写明路径,则存的数据将到目标目录下
(文件夹要提前建好)
#include <fcntl.h>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <string.h>
class ILSerializable
{
public:
virtual bool Serialize(FILE* fp) = 0;
virtual ILSerializable* Deserialize(FILE* fp) = 0;
virtual bool GetType(int& type) = 0;
public:
ILSerializable()
{
}
virtual ~ILSerializable()
{
}
};
class A : public ILSerializable
{
public:
A()
{
i = 0;
}
explicit A(int j)
{
i = j;
}
virtual ~A()
{
}
public:
void f()
{
std::cout << "in f(): " << i << std::endl;
}
public:
virtual bool GetType(int& type)
{
type = 0;
return true;
}
virtual bool Serialize(FILE *fp){
if(fp == NULL)
return false;
fwrite(&i, sizeof(int), 1, fp);
return true;
}
virtual ILSerializable* Deserialize(FILE *fp){
A *p = new A();
fread(&(p->i), sizeof(int), 1, fp);
return p;
}
private:
int i;
};
class B : public ILSerializable
{
public:
B()
{
i = 0;
j = 0;
}
explicit B(int k)
{
i = k;
j = k + 1;
}
virtual ~B()
{
}
public:
void f()
{
std::cout << "in f(): " << i << " " << j << std::endl;
}
public:
virtual bool GetType(int& type)
{
type = 1;
return true;
}
virtual bool Serialize(FILE *fp)
{
if(fp == NULL)
return false;
fwrite(&i, sizeof(int), 1, fp);
fwrite(&j, sizeof(int), 1, fp);
return true;
}
virtual ILSerializable* Deserialize(FILE* fp)
{
B *p = new B();
fread(&(p->i), sizeof(int), 1, fp);
fread(&(p->j), sizeof(int), 1, fp);
return p;
}
private:
int i;
int j;
};
class CLSerializer
{
public:
bool Serialize(const char *pFilePath, std::vector<ILSerializable*>& v)
{
FILE* fp = fopen(pFilePath, "w+");
if(fp == NULL)
return false;
for(int i = 0; i < v.size(); i++)
{
int type;
v[i]->GetType(type);
fwrite(&type, sizeof(int), 1, fp);
v[i]->Serialize(fp);
}
fclose(fp);
return true;
}
bool Deserialize(const char *pFilePath, std::vector<ILSerializable*>& v)
{
FILE* fp = fopen(pFilePath, "r+");
if(fp == NULL)
return false;
for(;;)
{
int nType = -1;
int r = fread(&nType, sizeof(int), 1, fp);
int type;
for(int i = 0; i < m_vSerialized.size(); i++)
{
m_vSerialized[i]->GetType(type);
if(type == nType)
{
ILSerializable *p = m_vSerialized[i]->Deserialize(fp);
if(p != NULL)
v.push_back(p);
}
}
if(r == 0)
break;
}
fclose(fp);
return true;
}
void Register(ILSerializable *pSerialized)
{
m_vSerialized.push_back(pSerialized);
}
private:
std::vector<ILSerializable*> m_vSerialized;
};
int main()
{
FILE *fp = fopen("config.txt", "r+");
char buf[100];
int len;
while(fgets(buf,100,fp) != NULL);
{
A a1(2);
B b1(3);
B b2(4);
A a2(5);
std::vector<ILSerializable*> v;
v.push_back(&a1);
v.push_back(&b1);
v.push_back(&b2);
v.push_back(&a2);
CLSerializer s;
s.Serialize(buf, v);
}
{
CLSerializer s;
A a;
B b;
s.Register(&a);
s.Register(&b);
std::vector<ILSerializable*> v;
s.Deserialize(buf, v);
for(int i = 0; i < v.size(); i++)
{
A *p = dynamic_cast<A *>(v[i]);
if(p != NULL)
p->f();
B *q = dynamic_cast<B *>(v[i]);
if(q != NULL)
q->f();
}
}
return 0;
}
循环读取config.txt中的文件路径,实现序列化和反序列化。