求自定义类对象序列化原理和方案
网络通信经常需要使用序列化,而C++又不像Java、C#本身就实现了序列化功能,那么C++如何对一个自定义类对象进行序列化和反序列化呢?请指教!另外,最好能够提供一些例程,谢谢!
如下面的类:
- C/C++ code
class msg{public: ... ...private: string id; string name; string data;};[解决办法]
1.提供一个私有方法 bool CircularBuffer::_Put(const void* pData, int nSize);
功能:将一段数据拷贝到自己的存储区。
2.重写每种类型的序列化方法
//下面是针对内建类型
template <typename T>
inline CircularBuffer & CircularBuffer::operator<<( const T& data )
{
Put(&data, sizeof(data));
return *this;
}
// 针对各种STL容器,以及自己定义的类
inline CircularBuffer& CircularBuffer::operator<< ( const std::string & str)
{
*this << str.size();
Put(str.c_str(), str.size());
return *this;
}
//
3 自己定义的类
class msg
{
public:
friend CircularBuffer& operator<< (CircularBuffer& cb, const msg& message)
{
return cb << message.id << message.name << message.data;
}
private:
string id;
string name;
string data;
};
[解决办法]
http://wenku.baidu.com/view/456122c30c22590102029d67.html
[解决办法]
可以看看boost的序列化库。
- C/C++ code
#include <fstream>#include <iostream>#include <boost/archive/text_oarchive.hpp>#include <boost/archive/text_iarchive.hpp>class A{private: //为了能让串行化类库能够访问私有成员,所以要声明一个友元类 friend class boost::serialization::access; //对象的数据 int a; double b; //串行化的函数,这一个函数完成对象的保存与恢复 template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & a; //就是这么简单,也可以使用 ar<<a 这样的语法 ar & b; }public: A(int aa, double bb) : a(aa), b(bb) { } A() { } void print() { std::cout << a << ' ' << b << std::endl; }};int main(){ std::ofstream fout("file.txt"); //把对象写到file.txt文件中 boost::archive::text_oarchive oa(fout); //文本的输出归档类,使用一个ostream来构造 A obj(1, 2.5); oa << obj; //保存obj对象 fout.close(); //关闭文件 std::ifstream fin("file.txt"); boost::archive::text_iarchive ia(fin); //文本的输入归档类 A newobj; ia >> newobj; //恢复到newobj对象 newobj.print(); fin.close(); system("pause"); return 0;}
[解决办法]
boost::serialization
protocol buffer
thrift
都有缺陷
protocol buffer
thrift
对自定义的类的成员对象不支持(我没用过)
boost::serialization
对自定义的类的成员的多态指针支持不好,不能自动识别。
C++下目前还没有java那样好的序列化,主要是C++没有反射
[解决办法]
Boost使用很简单。
否则象一楼说的一样也可以。
关键技巧在于,给你的类里写一个接口,序列化和反序列化都使用这个接口,
所以你具体的序列化方案,或接口中序列化变量的顺序都不重要。
Class ClassA{
int a;
int b;
ClassC c;
virtual void serialize(Archive& ar) //真正负责序列化或反序列化的是Archive的子类
{
ar.io(a);
ar.io(b);
ar.io(c)
}
}
class Archive{
virtual void io(int );
virtual void io(double );
template<class T> //递归自己定义的类
void io(T t){
t.io(*this);
}
}
Boost使用很简单。
否则象一楼说的一样也可以。
关键技巧在于,给你的类里写一个接口,序列化和反序列化都使用这个接口
Class ClassA{
int a;
int b;
ClassC c;
virtual void serialize(Archive& ar) //真正负责序列化或反序列化的是Archive的子类
{
ar.io(a);
ar.io(b);
ar.io(c)
}
}
class IArchive:public Archive{
virtual void io(int ){ 具体实现序列化}
virtual void io(double ){ 具体实现序列化}
}
class OArchive:public Archive{
virtual void io(int ){ 具体实现反序列化}
virtual void io(double ){ 具体实现反序列化}
}
[解决办法]
boost::serialization也不是完全不能序列化多态对象,
只是要在它的serialize函数中声明具体要序列化哪个子类。
如果你能忍受,直接用boost::serialization是最省事的。
C++可以模仿Java的反射,获取对象运行时类名,和通过类名构造动态构造对象。
不过实现方法比较变态。
看看
http://blog.csdn.net/wrq147/article/details/5603262
[解决办法]
按总长度, 数据区, 总长度, 数据区来直接读就是了.
在写入的时候, 通常都是能够知道自己写入多少读取多少的. 因为按顺序读取完成后就完成了. 除非你存在不确定大小的BUF要写进去, 而又为节省空间没有写明BUF的大小, 直接把剩余的东西都作为BUF的内容来读.
