前言:
本文以C++语言作为讲解序列化的作用。
序列化是什么?
一般说到序列化,其实是包含了反序列化。
以C++为例,序列化就是将结构体(或者是类)等复杂的数据结构的各个属性有序地保存到字符数组。而反序列化就是将有序的字符数组还原回结构体(或者是类)等复杂的数据结构。
序列化作用
1、方便网络传输
我们都知道,socket的数据都是以字符串进行传输,而序列化的作用就是将复杂的数据结构转换成字符串。
2、方便协议解释
序列化中的“序”就是有序的意思,有序的字符串序列可以供绝大多数的编程语言解释。而Protocol Buffers就是其中的突出代表。
3、方便数据存储
方便数据存储这个好理解,就是解决一对多的问题。不用序列化可能需要存储多条信息,而序列化可以将多条数据合成一条进行存储;方便数据运维。
序列化也是一把双刃剑,优点明显,缺点同样明显!
序列化的不足
1、性能
不是说序列化效率低下,而是人为在序列化上效率控制上。以在windows(VS2013)下为例,当我们对结构体进行赋值时,当结构体字节小于等于4096时,编译器会将结构体每个值进行一一赋值(这里的值不是真正结构的值,相对汇编来说是4个字节);当结构体字节大于4096时,编译器会直接调用memcpy。这是因为一一赋值的效率会随着字节数的增大而大幅下降。
2、存储数据不易修改
假如现在数据库保存的是a、b、c三个值的序列化的字符串。但是现在需求发生变化,需要加入d值。那就麻烦了,因为现在要考虑旧数据的兼容问题了。
对于性能问题,只能加强自身能力来确保性能的最大化。而对于存储数据,我的建议加入一个版本号,对这个版本号的不同做一些数据兼容。
我已经将我自己写的序列化代码放到github : https://github.com/XJM2013/Serializer 有兴趣的可以看看。下面贴出测试代码,及测试结果。
#ifndef TEST_SERIALIZER_H #define TEST_SERIALIZER_H #include <vector> #include "serializer.h" namespace TestSerializer { class TestData { public: TestData(){}; ~TestData(){}; bool Serialize(Serializer &stream) const; bool Unserialize(Serializer &stream); struct DataStruct { int a; short b; char c; char d; long long e; float f; double g; }; DataStruct m_data_struct; typedef std::vector<int> VECTOR_TEST; typedef std::vector<std::string> VECTOR_NAME; VECTOR_TEST role_data; VECTOR_NAME role_name; }; bool TestData::Serialize(Serializer &stream) const { stream.Push(m_data_struct); stream.Push(role_data.size()); for (VECTOR_TEST::const_iterator itr = role_data.begin(); itr != role_data.end(); ++itr) { stream.Push((*itr)); } stream.Push(role_name.size()); for (VECTOR_NAME::const_iterator itr = role_name.begin(); itr != role_name.end(); ++itr) { stream.PushStr(itr->c_str(), itr->length() + 1); } return true; } bool TestData::Unserialize(Serializer &stream) { stream.Pop(m_data_struct); unsigned int size = 0; stream.Pop(size); int data = 0; for (unsigned int i = 0; i < size; ++i) { stream.Pop(data); role_data.push_back(data); } stream.Pop(size); char *str = 0; unsigned int length = 0; bool ret = false; for (unsigned int i = 0; i < size; ++i) { ret = stream.PopStr(&str, length); if (!ret) { return ret; } role_name.push_back(str); } return true; } void Normal() { TestData src_data; TestData des_data; src_data.m_data_struct.a = 11; src_data.m_data_struct.b = 22; src_data.m_data_struct.c = 33; src_data.m_data_struct.d = 44; src_data.m_data_struct.e = 55; src_data.m_data_struct.f = (float)66.6; src_data.m_data_struct.g = -77.7; src_data.role_data.push_back(88); src_data.role_data.push_back(99); src_data.role_name.push_back("xian"); src_data.role_name.push_back("jia"); src_data.role_name.push_back("ming"); // src_data and des_data will be the same char data[1024] = { 0 }; Serializer temp1(data, 1024); src_data.Serialize(temp1); Serializer temp2(data, 1024); des_data.Unserialize(temp2); } } #endif
断点查看结果: