序列化和反序列化(简单)(c++)
最近看了看序列化相关的,动手试着做了一下。虽然感觉自己很菜,但还是忍不住分享。由此记录成长:
什么事序列化呢:(我的理解):
将数据转换成字节流存进内存:序列化
从指定内存取出字节流,再把字节流转换成数据:反序列化
那我们需要准备申请一块内存空间:
char* m_arr;
m_arr = new char[256];
我们取数据就需要精确的从内存里面找到该数据所在内存空间的下标:利用指针偏移
所以我们需要一个变量记录指针偏移量:
int m_index = 0;
比如下图中,第一个数据存的是一个int类型的数据,大小为4个字节,第二个为bool类型的数据,大小为1个字节。
存数据(因为是char*类型数组,所以赋值需要强转)
//value是外部传进来的int类型数据
*(int*)&m_arr[m_index] = value;
指针偏移
m_index +=sizeof(int);
//value是外部传进来的bool类型数据
*(bool*)&m_arr[m_index] = value;
m_index +=sizeof(bool);
反序列化就是直接反过来,利用指针偏移,拿到相应的数据,再根据自己所需要的类型进行强转:
存数据(因为是char*类型数组,所以赋值需要强转)
//value是外部传进来的int类型数据存储,调用了引用
value =*(int*)&m_arr[m_index] ;
指针偏移
m_index +=sizeof(int);
//value是外部传进来的bool类型数据存储,调用了引用
value = *(bool*)&m_arr[m_index];
m_index +=sizeof(bool);
按照上面的步骤,粘贴复制得到可以转换的其他类型就可以了:
不过容器需要特殊处理,原理差不多:
比如string类型:
//得到string大小,value是外部传进来的string类型数据
int szienum = value.size();
//将长度存进去,后面反序列化的时候就好拿数据长度了
oeprMath::operator<<(szienum);
for (int i = 0; i < szienum; i++)
{
//在把数据一个一个存进去
*(char*)&m_arr[m_index] = value[i];
m_index += 1;
}
取数据差不多:
int sizenum = *(int*)&m_arr[m_index];
m_index += sizeof(int);
string test = "";
for (int i = m_index; i < m_index + sizenum; i++)
{
char numa =m_arr[i];
if (numa)
{
test+=m_arr[i];
}
}
value = test;
m_index +=sizenum;
最后上我做的demo:c++版的
.h文件
#pragma once
#include <string>
using namespace std;
#define M_STRING 28;
#define M_BOOL 1;
#define M_INT 4;
#define M_SHORT 2;
#define M_LONG 4;
class oeprMath
{
public:
oeprMath();
~oeprMath();
void operator<<(bool& value);
void operator<<(int& value);
void operator<<(string& value);
void operator<<(long& value);
void operator<<(short& value);
void operator<<(char& value);
void operator>>(bool& value);
void operator>>(int& value);
void operator>>(string& value);
void operator>>(long& value);
void operator>>(short& value);
void operator>>(char& value);
char* arr();
void setarr(char* arr)
{
m_index = 0;
}
private:
char* m_arr;
int m_index = 0;
};
.cpp文件:
#include "oeprMath.h"
oeprMath::oeprMath()
{
m_arr = new char[256];
}
oeprMath::~oeprMath()
{
}
void oeprMath::operator<<(bool& value)
{
*(bool*)&m_arr[m_index] = value;
m_index += M_BOOL;
}
void oeprMath::operator<<(int& value)
{
*(int*)&m_arr[m_index] = value;
m_index += M_INT;
}
void oeprMath::operator<<(string& value)
{
int szienum = value.size();
//将长度存进去,后面反序列化的时候就好拿数据长度了
oeprMath::operator<<(szienum);
for (int i = 0; i < szienum; i++)
{
oeprMath::operator<<(value[i]);
}
}
void oeprMath::operator<<(long& value)
{
*(long*)&m_arr[m_index] = value;
m_index += M_LONG;
}
void oeprMath::operator<<(short& value)
{
*(short*)&m_arr[m_index] = value;
m_index += M_SHORT;
}
void oeprMath::operator<<(char & value)
{
*(char*)&m_arr[m_index] = value;
m_index += 1;
}
void oeprMath::operator>>(bool& value)
{
value=*(bool*)&m_arr[m_index];
m_index += M_BOOL;
}
void oeprMath::operator>>(int& value)
{
value =*(int*)&m_arr[m_index] ;
m_index += M_INT;
}
void oeprMath::operator>>(string& value)
{
int sizenum = *(int*)&m_arr[m_index];
m_index += M_INT;
string test = "";
for (int i = m_index; i < m_index + sizenum; i++)
{
char numa =m_arr[i];
if (numa)
{
test+=m_arr[i];
}
}
value = test;
m_index +=sizenum;
}
void oeprMath::operator>>(long& value)
{
value=*(long*)&m_arr[m_index];
m_index += M_LONG;
}
void oeprMath::operator>>(short& value)
{
value=*(short*)&m_arr[m_index];
m_index += M_SHORT;
}
void oeprMath::operator>>(char & value)
{
value = *(char*)&m_arr[m_index];
m_index += 1;
}
char* oeprMath::arr()
{
return m_arr;
}
main函数调用:
// socketSever.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <iostream>
#include <string>
#include "oeprMath.h"
using namespace std;
struct cscom
{
int id;
long name;
bool isopen;
string name1;
};
char *m_arr;
void write(oeprMath &oper,cscom &vo)
{
oper << vo.id;
oper << vo.name;
oper << vo.isopen;
oper << vo.name1;
}
void read(oeprMath &oper, cscom &vo)
{
oper >> vo.id;
oper >> vo.name;
oper >> vo.isopen;
oper >> vo.name1;
}
int main()
{
cout << sizeof(char) << endl;
cscom testcom;
testcom.id = 1;
testcom.name = 233;
testcom.name1 = "namess";
testcom.isopen = true;
oeprMath testmath;
write(testmath, testcom);
m_arr =testmath.arr();
cout << m_arr << endl;
cscom readarr;
testmath.setarr(testmath.arr());
read(testmath, readarr);
cout << readarr.id << endl << readarr.name << endl << readarr.isopen << endl << readarr.name1 << endl;
}
ps:序列化和反序列化的时候,存和取数据的结构不能乱。
就酱