建网站系统,网站建设续费合同,美食类网站开发需求,wordpress云标签From: http://www.cnblogs.com/lanxuezaipiao/p/3703988.html 导读 1. 什么是序列化#xff1f; 2. 为什么要序列化#xff1f;好处在哪里#xff1f; 3. C对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 正文 1. 什么是序列化#xff1f; 程序员在编写应用程序…From: http://www.cnblogs.com/lanxuezaipiao/p/3703988.html 导读 1. 什么是序列化 2. 为什么要序列化好处在哪里 3. C对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 正文 1. 什么是序列化 程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将 程序数据转化成能被存储并传输的格式的过程被称为“序列化”Serialization而它的逆过程则可被称为“反序列化” Deserialization。 简单来说序列化就是将对象实例的状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化它根据流重构对象。这两个过程结合起来可以轻 松地存储和传输数据。例如可以序列化一个对象然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。 总结 序列化将对象变成字节流的形式传出去。 反序列化从字节流恢复成原来的对象。 2. 为什么要序列化好处在哪里 简单来说对象序列化通常用于两个目的 1 将对象存储于硬盘上 便于以后反序列化使用 2在网络上传送对象的字节序列 对象序列化的好处在哪里网络传输方面的便捷性、灵活性就不说了这里举个我们经常可能发生的需求你 有一个数据结构里面存储的数据是经过很多其它数据通过非常复杂的算法生成的由于数据量很大算法又复杂因此生成该数据结构所用数据的时间可能要很久 也许几个小时甚至几天生成该数据结构后又要用作其它的计算那么你在调试阶段每次运行个程序就光生成数据结构就要花上这么长的时间无疑代价 是非常大的。如果你确定生成数据结构的算法不会变或不常变那么就可以通过序列化技术生成数据结构数据存储到磁盘上下次重新运行程序时只需要从磁盘上读 取该对象数据即可所花费时间也就读一个文件的时间可想而知是多么的快节省了我们的开发时间。 3. C对象序列化的四种方法 将C对象进行序列化的方法一般有四种下面分别介绍 3.1 Google Protocol Buffersprotobuf Google Protocol Buffers (GPB)是Google内部使用的数据编码方式旨在用来代替XML进行数据交换。可用于数据序列化与反序列化。主要特性有 高效 语言中立(Cpp, Java, Python) 可扩展 官方文档 3.2 Boost.Serialization Boost.Serialization可以创建或重建程序中的等效结构并保存为二进制数据、文本数据、XML或者有用户自定义的其他文件。该库具有以下吸引人的特性 代码可移植实现仅依赖于ANSI C。 深度指针保存与恢复。 可以序列化STL容器和其他常用模版库。 数据可移植。 非入侵性。 3.3 MFC Serialization Windows平台下可使用MFC中的序列化方法。MFC 对 CObject 类中的序列化提供内置支持。因此所有从 CObject 派生的类都可利用 CObject 的序列化协议。 MSDN中的介绍 3.4 .Net Framework .NET的运行时环境用来支持用户定义类型的流化的机制。它在此过程中先将对象的公共字段和私有字段以及类的名称包括类所在的程序集转换为字节流然后再把字节流写入数据流。在随后对对象进行反序列化时将创建出与原对象完全相同的副本。 3.5 简单总结 这几种序列化方案各有优缺点各有自己的适用场景。其中MFC和.Net框架的方法适用范围很窄只适用于Windows下且.Net框架方法还需要.Net的运行环境。参考文献1从序列化时间、反序列化时间和产生数据文件大小这几个方面比较了前三种序列化方案得出结论如下仅供参考 Google Protocol Buffers效率较高但是数据对象必须预先定义并使用protoc编译适合要求效率允许自定义类型的内部场合使用。 Boost.Serialization 使用灵活简单而且支持标准C容器。 相比而言MFC的效率较低但是结合MSVS平台使用最为方便。 为了考虑平台的移植性、适用性和高效性推荐大家使用Google的protobuf和Boost的序列化方案下面介绍我使用这两种方案的心得及注意事项。 4. 最常用的两种序列化方案使用心得 关于这两种方案的具体使用和示例没什么好写的因为优秀的参考资料很多请看后面给出的相关参考资料这里只给出我使用时的一些心得方便大家在选择序列化方案时有个正确的参考避免选择错误浪费时间。 4.1 Google Protocol Buffers protobuf相对而言效率应该是最高的不管是安装效率还是使用效率protobuf都很高效而且protobuf不仅用于C序列化还可用于Java和Python的序列化使用范围很广。但在使用过程中要注意两个问题 1protobuf支持的数据类型不是很丰富 protobuf属于轻量级的因此不能支持太多的数据类型下面是protobuf支持的基本类型列表一般都能满足需求不过在选择方案之前还是先看看是否都能支持以免前功尽弃。同样该表也值得收藏作为我们在定义类型时做参考。 .proto type c notes double double float float int32 int32 使用可变长编码方式负数时不够高效应该使用sint32 int64 int64 同上 uint32 uint32 使用可变长编码方式 uint64 uint64 同上 sint32 int32 使用可变长编码方式有符号的整型值编码时比通常的int32高效 sint64 sint64 同上 fixed32 uint32 总是4个字节如果数值总是比2^28大的话这个类型会比uint32高效 fixed64 uint64 总是8个字节如果数值总是比2^56大的话这个类型会比uint64高效 sfixed32 int32 总是4个字节 sfixed64 int64 总是8个字节 bool bool string string 一个字符串必须是utf-8编码或者7-bit的ascii编码的文本 bytes string 可能包含任意顺序的字节数据 2protobuf不支持二维数组指针不支持STL容器序列化 这个缺陷挺大因为稍复杂点的数据结构或类结构里出现二维数组、二维指针和STL容器set、list、map等很频繁但因为 protobuf简单的实现机制只支持一维数组和指针用repeated修饰符修饰不能使用repeated repeated来支持二维数组 也不支持STL因此在选择该方案之前一定 要确保你的数据结构里没有这些不支持的类型。 3protobuf嵌套后会改变类名称 protobuf支持类的嵌套即在一个自定义类型中可以定义另一个自定义类型但注意嵌套的自定义类型在经过protobuf处理后生成的类名称并不是你定义的类名称而是加上了外层的类名称作为前缀下面举一个简单的例子 message DFA {
required int32 _size 1;
message accept_pair {
required bool is_accept_state 1;
required bool is_strict_end 2;
optional string app_name 3;
}
repeated accept_pair accept_states 2;
} 那么嵌套中的accept_pair 生成后的类不是accept_pair 而是DFA_accept_pair 。如果不想改类名称将accept_pair 拿到外面与DFA平行定义即可。 4.2 Boost.Serialization Boost库是个很庞大的库功能非常丰富序列化只是其中的一个小分支但为了使用Boost的序列化方案你需要安装整个Boost库所花费的磁盘空间和时间都很多同样支持的序列化功能也很强大既支持二维数组指针也支持STL容器更不需要我们用某种特殊的格式重新定义我们的类结构其非侵入的性质使得我们无须改动已有的类结构即可序列化这时非常赞的一个性质。但是由于体积庞大安装复杂如果只是简单的序列化没必要使用该方案只有protobuf不能满足你的需求时才应该考虑该方案。 1安装boost库遇到的一系列问题 安装boost库本事就是一项很费时的工程如果期间出现了各种错误更加耗时耗耐心。我们可以从官网下载Boost库的二进制源码进行安装安装方法可以参考网络或后面我给出的参考资料。 安装过程如下 首先解压安装包如果是tar.gz用tar zxvf解压如果是tar.bz2用tar jxvf解压解压后进入解压后的目录依次运行以下命令 ./bootstrap.sh
sudo ./b2 install 注这里没有指定安装路径在第二个命令可以加入--prefix指定安装目录。 安装时的注意事项 注意1要用root权限进行安装否则会在安装过程中报错提示权限不足。 注意2boost库的安装依赖一些环境通常有Python、bzip2和zlib它们所在的软件包分别为 Ubuntu下 zlib1g-dev
libbz2-dev
libpython2.7-dev (and libpython3.3-dev) Fedora/Redhat下 zlib-devel
libbz2-devel
python-devel (and python3-devel) 这也是安装过程中报错的主要来源。 报错1如果Python库不完整可能会报“ fatal error: pyconfig.h: No such file or directory compilation terminated.”或者“fatal error: patchlevel.h: No such file or directory”错误。解决方法如下 Fedora系统sudo yum install python-devel Ubuntu系统sudo apt-get install python-dev 报错2报错 “ libs/iostreams/src/bzip2.cpp:20:56: fatal error: bzlib.h: No such file or directory”解决方案 Fedora系统sudo yum install bzip2-devel Ubuntu系统或Debian系统sudo apt-get install libbz2-dev 通常对于这些错误在Ubuntu系统下一般可以通过sudo apt-get install libboost-all-dev全部解决但不一定行得通。 2安装成功后如果未指定安装位置那么默认将会安装到/usr/local/lib和/usr/local/include下那么我们在使用Boost库进行编译时就需要使用-L和-I参数加上具体的lib和include路径像下面这样 g -o test boost_test.cpp -I$BOOST_INCLUDE -L$BOOST_LIB -lboost_serialization 如果觉得每次都这样很麻烦那么可以将我们所要用到的lib和include文件加入到环境变量中像下面这样 sudo cp /usr/local/lib/libboost_serialization.* /usr/lib
sudo cp -r /usr/local/include/boost /usr/include 然后在编译时直接g -o test boost_test.cpp -lboost_serialization即可。 注意boost下面有两个序列化lib文件ibboost_serialization.lib 和 libboost_wserialization.lib那么这两者有什么区别呢 其实w 表示使用的是宽字符例如 wchar_t。 3boost不尽人意的地方 基本类型指针很难序列化例如int *array官网上是这么说的 By default, data types designated primitive byImplementation Levelclass serialization trait are never tracked. If it is desired totrack a shared primitive object through a pointer (e.g. alongused as a reference count), It should be wrappedin a class/struct so that it is an identifiable type.The alternative of changing the implementation level of alongwould affect alllongs serialized in the wholeprogram - probably not what one would intend. 也就是说如果你想序列化原生类型的指针需要给其加上struct或class使其变为类类型再序列化可见有些麻烦这样的需求往往也很频繁鉴于序列化机制的实现原理boost库暂时还不能很好的支持基本类型的指针序列化。 不能序列化变长数组variable-sized array会报错说变长数组不是模板类类型。 4如果需要定义一个对象数组如定义含有2个元素的class A对象数组那么必须用A a[2]定义而不能用对象的指针A *a new A[2]定义这样序列化a后默认当作一个A对象处理因此只能存储一个对象的值后面的不会存储。 5所谓boost很人性的非侵入性质也有一定的条件如果不想改动原来的类那么原来的类属性必须是public的这很容易解释因为你必须 要能在别处访问到这些属性并定义其序列化方式当然这也在其它地方暴露了类的结构具有一定的劣势。这样的条件往往很难满足因为我们定义的类属性一般都 是private的如果是这样且仍想要使用非侵入性质那么需要在类中添加以下声明来开放访问给 serialization 库 friend class boost::serialization::access; 这样的方式比让成员public更好。 参考资料 常见的三种C序列化方案对比 c对象序列化初步探讨 官方介绍Google Protocol Buffers Google Protocol Buffers中文教程 Protocol Buffers的应用与分析 玩转Protocol Buffers BoostGetting Started on Unix Variants linux平台上编译安装boost库新浪博客 Boost Serialization 库 Boost C库 - 序列化 Boost - 序列化 (Serialization) Boost - Serialization序列化 作者Alexia(minmin) 如果您认为阅读这篇博客让您有些收获不妨点击一下右下角的【推荐】 如果您希望与我交流互动欢迎微博互粉 本文版权归作者和博客园共有欢迎转载但未经作者同意必须保留此段声明且在文章页面明显位置给出原文连接否则保留追究法律责任的权利。