序列化的作用

前言:

本文以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/GameEngine/blob/master/lib/src/common/serializer.cpp 有兴趣的可以看看。下面贴出测试代码,及测试结果。

    #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  

断点查看结果:


原文地址:http://blog.csdn.net/yitouhan/article/details/42171519

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值