在text_oarchive
上用boost::serialization
序列化std::string
时遇到问题。AFAICT,我有两段相同的代码,在两个不同的程序中表现不同。
这是我认为运行正确的程序:
#include <iostream>
#include <string>
#include <sstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
template <typename T>
void serialize_deserialize(const T & src, T & dst)
{
std::string serialized_data_str;
std::cout << "original data: " << src << std::endl;
std::ostringstream archive_ostream;
boost::archive::text_oarchive oarchive(archive_ostream);
oarchive << src;
serialized_data_str = archive_ostream.str();
std::cout << "serialized data: " << serialized_data_str << std::endl;
std::istringstream archive_istream(serialized_data_str);
boost::archive::text_iarchive iarchive(archive_istream);
iarchive >> dst;
}
int main()
{
std::string archived_data_str = "abcd";
std::string restored_data_str;
serialize_deserialize<std::string>(archived_data_str, restored_data_str);
std::cout << "restored data: " << restored_data_str << std::endl;
return 0;
}
这是它的输出:
original data: abcd
serialized data: 22 serialization::archive 10 4 abcd
restored data: abcd
(可以使用:g++ boost-serialization-string.cpp -o boost-serialization-string -lboost_serialization
)进行编译
另一方面,这是我正在编写的程序的摘录(源自boost_asio/example/serialization/connection.hpp),该程序序列化std::string
数据,将每个字符转换为十六进制表示:
/// Asynchronously write a data structure to the socket.
template <typename T, typename Handler>
void async_write(const T& t, Handler handler)
{
// Serialize the data first so we know how large it is.
std::cout << "original data: " << t << std::endl;
std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);
archive << t;
outbound_data_ = archive_stream.str();
std::cout << "serialized data: " << outbound_data_ << std::endl;
[...]
这是它的输出摘录:
original data: abcd
serialized data: 22 serialization::archive 10 5 97 98 99 100 0
版本(10
)是一样的,对吧?这应该证明我在两个程序中使用了相同的序列化库。
然而,我真的不明白这里发生了什么。我几乎整个工作日都在努力解决这个难题,但我已经无计可施了。
对于任何想要重现这个结果的人来说,下载Boost序列化示例就足够了,添加以下行
connection_.async_write("abcd", boost::bind(&client::handle_write, this, boost::asio::placeholders::error));
在client.cpp
的第50行,在client.cpp 中添加以下成员函数
/// Handle completion of a write operation.
void handle_write(const boost::system::error_code& e)
{
// Nothing to do. The socket will be closed automatically when the last
// reference to the connection object goes away.
}
添加此cout
:
std::cout << "serialized data: " << outbound_data_ << std::endl;
在connection.hpp:59
并使用进行编译
g++ -O0 -g3 client.cpp -o client -lboost_serialization -lboost_system
g++ -O0 -g3 server.cpp -o server -lboost_serialization -lboost_system
我在Ubuntu 13.04 64bit
和Boost 1.53
下使用g++ 4.8.1
如有任何帮助,我们将不胜感激。
附言:我之所以发布此消息,是因为std::string
的反序列化根本不起作用!:)
我看到了导致这种行为的两个原因。
- 编译器不会显式地将
"abcd"
从const char *
转换为std::string
,并且序列化将其作为"字节"的矢量而不是ASCII字符串进行处理。将代码更改为connection_.async_write(std::string("abcd"), boost::bind(&client::handle_write, this, boost::asio::placeholders::error));
应该可以解决问题 - 可能,作为
async_write
模板方法的t
参数传递的字符串类型不是std::string
,而是std::wstring
,它不是作为ASCII字符串("abcd")序列化的,而是作为无符号短矢量序列化的,97 98 99 100
是ASCII字符a
、b
、c
和d
的十进制表示