升压序列化二进制归档给予不正确的输出 [英] Boost Serialization Binary Archive giving incorrect output
问题描述
我试图序列化类。
类定义:
类StartPeerSessionRequest {
上市:
StartPeerSessionRequest();
虚拟〜StartPeerSessionRequest();
虚空composeRequestwithHard codeValues();
无效保存();
stringstream的serializedRequest;
/ *的boost ::系列化:: binary_object serlreq; * /私人的:
StartPeerSessionRequest(常量StartPeerSessionRequest&安培;); uint16_t mProtocolVersion;
uint16_t mSessionFlags;
uint16_t mMaxResponseLength;
串mMake;
串模型探讨;
串mSerialNumber;
uint8_t有mTrackDelay;
串mHeadUnitModel;
串mCarModelYear;
串MVIN;
uint16_t mVehicleMileage;
uint8_t有mShoutFormat;
uint8_t有mNotificationInterval; 友元类的boost ::系列化::访问;
模板< typename的归档和GT;无效连载(归档和放大器; AR,const的无符号整型版);
};StartPeerSessionRequest :: StartPeerSessionRequest(){ mProtocolVersion = 1 * 10000 + 14 * 100 + 4;
mSessionFlags = 1;
mMaxResponseLength = 0;
mMake =MyMake;
模型探讨=为MyModel;
mSerialNumber =10000;
mTrackDelay = 0;
mHeadUnitModel =音响本体;
mCarModelYear =2014;
MVIN =1234567980;
mVehicleMileage = 1000;
mShoutFormat = 3;
mNotificationInterval = 1;
}模板<类归档和GT;无效StartPeerSessionRequest ::连载(归档和放大器; AR,const的无符号整型版){
AR&安培; mProtocolVersion;
AR&安培; mSessionFlags;
AR&安培; mMaxResponseLength;
AR&安培; mMake;
AR&安培;模型探讨;
AR&安培; mSerialNumber;
AR&安培; mTrackDelay;
AR&安培; mHeadUnitModel;
AR&安培; mCarModelYear;
AR&安培; MVIN;
AR&安培; mVehicleMileage;
AR&安培; mShoutFormat;
AR&安培; mNotificationInterval;
}无效StartPeerSessionRequest ::保存(){
提高::档案:: binary_oarchive OA(serlreq,提振::档案:: no_header);
OA<< (*这个);
/ * COUT<<\\ n binary_oarchive:<< serlreq.size(); * / 提高::档案:: text_oarchive的OTA(serializedRequest,提振::档案:: no_header);
OTA<< (*这个);
COUT<< \\ n text_oarchive:<< serializedRequest.str()&所述;&下; 大小:<< serializedRequest.str()的大小()。
}
serializedRequest.str.size()
为我提供的87长度
其实应该给我65个字节。 (我数u能明白这一点从构造)
我怀疑它是介于两者之间的长度追加
我已经尝试使用 text_archive
也是它不工作。
我需要的是只是简单的序列化类成员,因为它是。
我想我需要使用一些特征或包装。
请让我知道
感谢
好了,所以,就看我怎么会做,我试图达到最佳尺寸我算了算<一个href=\"http://stackoverflow.com/questions/26556145/boost-serialization-binary-archhive-giving-incorrect-output#comment41745393_26556145\">on我的餐巾背面:
我可以看到你是如何想到57,63,或75字节
mProtocolVersion = 1 * 10000 + 14 * 100 + 4; // 2字节
mSessionFlags = 1; // 2字节
mMaxResponseLength = 0; // 2字节
mMake =MyMake; // 6个字节长度+
模型探讨=为MyModel; // 7个字节长度+
mSerialNumber =10000; // 5个字节长度+
mTrackDelay = 0; // 1字节
mHeadUnitModel =音响本体; // 8字节长度+
mCarModelYear =2014; // 4个字节长度+
MVIN =1234567980; // 10个字节长度+
mVehicleMileage = 1000; // 2字节
mShoutFormat = 3; // 1字节
mNotificationInterval = 1; // 1字节
// // -------------------------------------- 51个字节+ 6×长度
块引用>在这种情况下,我创建二进制序列化code。使用升压精神(噶序列化和齐作反序列化)。我做了长度字段的配置规模(8,16,32或64位无符号)。
下面是一个概念证明工作: 住在Coliru
生成()
该常量生成成员函数的代表在一个单独的命名空间中的工作,辅助功能:
模板&LT; typename的集装箱&GT;
布尔生成(集装箱和放大器;字节)const的{
自动出=的std :: back_inserter(字节); 使用my_serialization_helpers :: do_generate;
返回do_generate(满分,mProtocolVersion)
&功放;&安培; do_generate(出,mSessionFlags)
&功放;&安培; do_generate(出,mMaxResponseLength)
&功放;&安培; do_generate(出,mMake)
&功放;&安培; do_generate(出,模型探讨)
&功放;&安培; do_generate(出,mSerialNumber)
&功放;&安培; do_generate(出,mTrackDelay)
&功放;&安培; do_generate(出,mHeadUnitModel)
&功放;&安培; do_generate(出,mCarModelYear)
&功放;&安培; do_generate(出,MVIN)
&功放;&安培; do_generate(出,mVehicleMileage)
&功放;&安培; do_generate(出,mShoutFormat)
&功放;&安培; do_generate(出,mNotificationInterval);
}注意
do_generate
重载可以随意根据需要为未来的加类型- 容器可以很容易地从例如切换
的std ::矢量&lt; unsigned char型&GT;
,例如要的boost ::进程间::容器::字符串&LT;焦炭,char_traits&LT;焦炭&gt;中的boost ::进程间::分配器&LT;焦炭,提高::进程间:: managed_shared_memory :: segment_manager&GT;方式&gt;
解析()
解析方法不同的是它委托给非常相似
do_parse
重载做的工作。测试
测试程序与所有可能的配置来回:
- 8位长度字段, 网57字节 与升压系列化:70
- 16位的长度字段, 网63字节 与升压系列化:76
- 32位的长度字段, 网75个字节 与升压系列化:88
- 64位的长度字段, 网99字节 与升压系列化:112
正如你可以看到它甚至不是的是的离谱的是,自然加速系列化解决方案,<一个href=\"http://stackoverflow.com/questions/26556145/boost-serialization-binary-archhive-giving-incorrect-output#comment41736250_26556145\">would采取我的系统 107字节(这比我上次配置的只有8个字节)。
还要注意,由于噶发电机全部采取任何输出迭代器,它应该是比较容易直接接线入的低级别提升归档操作 性能和避免分配中间存储。
I am trying to Serialize a class.
Class definition:
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()
provides me a length of 87Actually it should provide me 65 bytes. (I've counted u can figure that out from the constructor)
I suspect it is appending lengths in between.
I have tried using
text_archive
also it doesnt work.What I need is to just plain serialize class members as it is.
I guess i need to use some traits or wrappers.
Please let me know
Thanks
解决方案Okay, so, just to see how I'd do, I've tried to reach the optimum sizes I calculated on the back of my napkin:
I can see how you'd expect 57, 63, or 75 bytes
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
In this instance, I created binary serialization code using Boost Spirit (Karma for serialization and Qi for de-serialization). I made the size of the length field configurable (8,16,32 or 64 bit unsigned).
Here's a working proof of concept: Live On Coliru
generate()
The const generate member function delegates the work to helper functions in a separate namespace:
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); }
Note that
do_generate
overloads can be freely added as required for future types- the container can easily be switched from e.g.
std::vector<unsigned char>
, to e.g.boost::interprocess::containers::string<char, char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> >
.
parse()
The parse method is very similar except it delegates to
do_parse
overloads to do the work.Testing
The test program roundtrips with all possible configurations:
- 8-bit length field, net 57 bytes, with boost serialization: 70
- 16-bit length field, net 63 bytes, with boost serialization: 76
- 32-bit length field, net 75 bytes, with boost serialization: 88
- 64-bit length field, net 99 bytes, with boost serialization: 112
As you can see it's not even that outrageous that the natural Boost Serialization solution would take 107 bytes on my system (it's only 8 bytes more than my last configuration).
Note also, that since the Karma generators all take any output iterator, it should be relatively easy to wire it directly into the low-level Boost Archive operations for performance and to avoid allocating intermediate storage.
这篇关于升压序列化二进制归档给予不正确的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!