Boost序列化二进制存档给出错误的输出
Boost Serialization Binary Archive giving incorrect output
我正在尝试序列化一个类。
类别定义:
class StartPeerSessionRequest {
public:
StartPeerSessionRequest();
virtual ~StartPeerSessionRequest();
void composeRequestwithHardCodeValues();
void save();
stringstream serializedRequest;
/*boost::serialization::binary_object serlreq;*/
private:
StartPeerSessionRequest(const StartPeerSessionRequest &);
uint16_t mProtocolVersion;
uint16_t mSessionFlags;
uint16_t mMaxResponseLength;
string mMake;
string mModel;
string mSerialNumber;
uint8_t mTrackDelay;
string mHeadUnitModel;
string mCarModelYear;
string mVin;
uint16_t mVehicleMileage;
uint8_t mShoutFormat;
uint8_t mNotificationInterval;
friend class boost::serialization::access;
template <typename Archive> void serialize(Archive &ar, const unsigned int version);
};
StartPeerSessionRequest::StartPeerSessionRequest() {
mProtocolVersion = 1 * 10000 + 14 * 100 + 4;
mSessionFlags = 1;
mMaxResponseLength = 0;
mMake = "MyMake";
mModel = "MyModel";
mSerialNumber = "10000";
mTrackDelay = 0;
mHeadUnitModel = "Headunit";
mCarModelYear = "2014";
mVin = "1234567980";
mVehicleMileage = 1000;
mShoutFormat = 3;
mNotificationInterval = 1;
}
template <class Archive> void StartPeerSessionRequest::serialize(Archive &ar, const unsigned int version) {
ar & mProtocolVersion;
ar & mSessionFlags;
ar & mMaxResponseLength;
ar & mMake;
ar & mModel;
ar & mSerialNumber;
ar & mTrackDelay;
ar & mHeadUnitModel;
ar & mCarModelYear;
ar & mVin;
ar & mVehicleMileage;
ar & mShoutFormat;
ar & mNotificationInterval;
}
void StartPeerSessionRequest::save() {
boost::archive::binary_oarchive oa(serlreq, boost::archive::no_header);
oa << (*this);
/*cout<<"n binary_oarchive :"<<serlreq.size();*/
boost::archive::text_oarchive ota(serializedRequest, boost::archive::no_header);
ota << (*this);
cout << "n text_oarchive :" << serializedRequest.str() << "size :" << serializedRequest.str().size();
}
serializedRequest.str.size()
为我提供了87 的长度
实际上它应该为我提供65个字节。(我已经数过了,你可以从构造函数中计算出来)
我怀疑它在两者之间增加了长度。
我试过使用text_archive
,但它也不起作用。
我需要的只是简单地序列化类成员
我想我需要使用一些特征或包装。
请让我知道
感谢
好吧,为了看看我会怎么做,我试着达到我在餐巾纸背面计算的最佳尺寸:
我可以看到你对57、63或75字节的期望
mProtocolVersion = 1*10000+14*100+4; // 2 bytes mSessionFlags = 1; // 2 bytes mMaxResponseLength = 0; // 2 bytes mMake = "MyMake"; // 6 bytes + length mModel = "MyModel"; // 7 bytes + length mSerialNumber = "10000"; // 5 bytes + length mTrackDelay = 0; // 1 byte mHeadUnitModel = "Headunit"; // 8 bytes + length mCarModelYear = "2014"; // 4 bytes + length mVin = "1234567980"; // 10 bytes + length mVehicleMileage = 1000; // 2 byte mShoutFormat = 3; // 1 byte mNotificationInterval = 1; // 1 byte // -------------------------------------- // 51 bytes + 6 x length
在这个例子中,我使用Boost Spirit创建了二进制序列化代码(Karma用于序列化,Qi用于反序列化)。我使长度字段的大小可配置(8,16,32或64位无符号)。
这是一个有效的概念验证:在Coliru上直播
generate()
constgenerate成员函数将工作委托给单独命名空间中的辅助函数:
template <typename Container>
bool generate(Container& bytes) const {
auto out = std::back_inserter(bytes);
using my_serialization_helpers::do_generate;
return do_generate(out, mProtocolVersion)
&& do_generate(out, mSessionFlags)
&& do_generate(out, mMaxResponseLength)
&& do_generate(out, mMake)
&& do_generate(out, mModel)
&& do_generate(out, mSerialNumber)
&& do_generate(out, mTrackDelay)
&& do_generate(out, mHeadUnitModel)
&& do_generate(out, mCarModelYear)
&& do_generate(out, mVin)
&& do_generate(out, mVehicleMileage)
&& do_generate(out, mShoutFormat)
&& do_generate(out, mNotificationInterval);
}
注意
do_generate
过载可以根据未来类型的需要自由添加- 容器可以容易地从例如
std::vector<unsigned char>
切换到例如boost::interprocess::containers::string<char, char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> >
parse()
parse方法非常相似,只是它委托do_parse
重载来完成工作。
测试
测试程序使用所有可能的配置进行往返:
- 8位长度字段,净57字节,具有boost序列化:70
- 16位长度字段,净63字节,具有boost序列化:76
- 32位长度字段,net 75字节,具有boost序列化:88
- 64位长度字段,净99字节,具有boost序列化:112
正如您所看到的,自然Boost Serialization解决方案在我的系统上占用107个字节(只比我上次的配置多了8个字节),这甚至还不算太离谱。
还要注意的是,由于Karma生成器都采用任何输出迭代器,因此为了提高性能和避免分配中间存储,将其直接连接到低级Boost Archive操作应该相对容易。
对于Boost Serialization应该如何序列化为其专有的、不可移植的二进制格式,您似乎有一些非常具体的假设。
Boost序列化更高级,或多或少是专门为处理非POD数据而设计的。如果您坚持,您应该能够直接序列化POD类型的数组。然而,在您的问题中,该类根本不是POD,因此无论如何都不能按位序列化。
有关可移植档案,请参阅EOS可移植档案。
Boost Archives有可选的标志来抑制格式头:
enum archive_flags {
no_header = 1, // suppress archive header info
no_codecvt = 2, // suppress alteration of codecvt facet
no_xml_tag_checking = 4 // suppress checking of xml tags - igored on saving
};
请参阅归档模型
这里有一个背景,看看是什么引入了简单的按位序列化的开销:
- 提升C++序列化开销
- 如何使用自定义库的boost库进行性能测试
- 分段错误当我试图运行程序时出错
- .h 和.cpp文件分离时出错,但仅使用 .h 文件时没有错误.我做错了什么?
- 创建 OpenCV 非自由版本 v4.3 时出错,可折叠.cpp错误 C2039、2605
- 制作时出错,C++"db.c:2127:错误:在"||"标记之前应使用";"
- C++语法错误,编译器不会警告或 int v = func(&v) 出错;
- 在VS2015中访问类成员时运行时错误,但在Linux上未访问时出错
- 如何更改路径以修复错误"./main:加载共享库 libmkl_core.so 时出错?
- 为什么在定义类之前声明类的对象会在友元类中给出错误,而在友元函数中不会出错
- 安装 mply 库时出错.致命错误:gsl/gsl_sf.h:没有这样的文件或目录
- Rcpp/C++/R:比较日期时间矢量与日期时间时出错(错误:"运算符>"的不明确重载)
- 编译特征程序时出错:错误:'seq'不是'Eigen'的成员
- 可能的 GCC 链接器错误会导致将弱符号和局部符号链接在一起时出错
- 非标准语法;使用 '&' 创建指向成员的指针错误,将成员函数分配给向量时出错
- 运算符重载时出错(错误:"运算符<<不匹配(操作数类型为"std::basic_ostream<char>"和"const char [2]")
- 编译类 C++ 中的线程时出错(错误 xthread)
- 加载GLEW库时出错(错误LNK2001)
- 通过函数指针调用函数时出错(错误C2064)
- 编译core.obj时出错:错误LNK2001:未解析的外部符号_harmony_core_init
- 链接c++静态库与android ndk时出错(错误:无法识别文件格式)
- 使用GCC编译游戏时出错.(错误:将"Screen"的含义从"class Screen&q