文章目录
1.背景描述
在业务中,在读写binary的文件的时候,会统一使用同一binary接口。由于当前的binary接口严格按照顺序进行读写,导致对文件中字段的任何删减,都会造成业务使用新接口对文件的解析失败,程序崩溃。
2.方案描述
2.1 使用的库
使用boost serialization
库,本项目中无需导入额外的库,用到的库主要有以下
并且在makefile
中添加编译选项-lboost_serialization
2.2 面向场景
-
新的读写接口读取旧的文件,面向增删改的情况,都可读取成功
-
旧的读写接口读取新的文件,提示“当前版本过低,应更新接口版本”,程序正常退出
2.3 基本开发方案
-
添加类成员函数
serialize()
,序列化和反序列化都将调用该接口,将所有的成员变量都添加进来,其中的顺序可以自己定义。所有的STL包括map
、vector
等都将自动序列化。其中,因为成员变量都是
private
属性,我们添加友元boost::serialization::access
。 -
除此以外,所有的成员变量,如果是内置类型的,都同样需要添加以上的成员函数
-
在类的最后,我们为其添加版本控制宏,如不添加,默认的
version
为0。具体如何使用在后面有说明。
当一个类被添加了BOOST_CLASS_VERSION
后,会在序列化和反序列化的时候将该参数作为void serializa()
的const unsigned int version
传入。 -
实际序列化时,以二进制和写文件模式打开文件到
ofstream
(文件流),以此初始化一个binary_oarchive
对象,直接将对象输入到流中,即可完成序列化。 -
反序列化时,以二进制和读文件模式打开文件到
ifstream
(文件流),输出到一个指向对象的指针即可(由于序列化的时候输入的是指向对象的指针,所以反序列化的时候也使用指针)。
2.4 具体实现方案
主要面对以下场景
2.4.1 新接口读旧文件
1)增加了字段
比如新版本添加了m_test
字段,在序列化函数中添加对当前版本的判断
由于旧文件没有该属性,因此反序列化出来的对象的m_test
是默认值。
2)删除了字段
比如新版本不再需要m_test
字段,此时需要注意,为了版本控制,需要在高版本代码中保留该成员变量(不可删除),同时添加版本控制代码如下,在低版本中序列化删除的字段,高版本则跳过
3)修改了字段
道理上跟上一条一样,如将m_test1
的类型进行修改,需要保留原来的变量,同时添加版本控制代码。读旧文件时,m_test2
为默认值,m_test1
有值;读新文件时,m_test2
有值,m_test1
为默认值。
2.4.2 旧接口读新文件
抛出异常,提示接口版本过旧,需要更新接口(具体处理可再细化)。
实际运行效果,无异常提示,程序正常退出。
3 未来规划
设计具体接口,并和业务下游对接,将接口的改动降低到最小甚至没有。