【问题标题】:c++ boost serialization with stringstream时间:2019-05-10 标签:c++boostserializationwithstringstream
【发布时间】:2011-07-08 11:00:25
【问题描述】:

我是 boost 和 c++ 的新手,正在尝试将一个对象序列化为二进制然后反序列化它。

我正在使用示例中的类:http://en.highscore.de/cpp/boost/serialization.html

所以假设这是我要序列化的类:

class person 
{ 
public: 
  person() { } 

  person(int age) : age_(age) {  } 

  int age() const { return age_; } 

private:
  friend class boost::serialization::access;

  template <typename Archive>
  void serialize(Archive &ar, const unsigned int version)
  {
    ar & age_;
  }

  int age_;
}; 

这是序列化代码:

const char * save(Object ss)
{
    boost::archive::binary_oarchive oa(ss);
    person p(31);
    oa << p;

    return ss.str().data();
}

这是反序列化代码:

void load(const char * str)
    {

        stringstream s;
        s << str;

        boost::archive::binary_iarchive ia(s);
        person p;
        ia >> p;
        std::cout << p.age() << std::endl;

    }

当我尝试运行此代码时,我收到此错误:

terminate called after throwing an instance of 'boost::archive::archive_exception'
  what():  stream error

这让我问,有没有正确的方法来做到这一点?

谢谢,非常感谢。

编辑: 此版本有效:

这是序列化代码:

string save()
{
    boost::archive::binary_oarchive oa(ss);
    person p(31);
    oa << p;

    return ss.str();
}

这是反序列化代码:

void load(string str)
    {

        stringstream s;
        s << str;

        boost::archive::binary_iarchive ia(s);
        person p;
        ia >> p;
        std::cout << p.age() << std::endl;

    }

编辑2: 这个版本不工作。将感谢 cmets 修复。谢谢。

void Serialization::save()
{
    stringstream ss;
    {
        boost::archive::binary_oarchive oa(ss);
        person p(31);
        oa << p;
     }


        const char * temp1 = ss.str().data();

        stringstream s;
        s << temp1;

        cout << "UNSERIALIZING\n";
        boost::archive::binary_iarchive ia(s);
        person p1;
        ia >> p1;
        std::cout << p1.age() << std::endl;

}

【问题讨论】:

    标签: c++ serialization boost binary


    【解决方案1】:

    允许使用带有std::stringstream 的二进制存档,因为任何字符都可以存储在std::stringstream/std::string 中。

    问题是将结果数据作为空终止的 C 字符串传递,因为二进制数据极有可能嵌入空值,因此在加载时您的数据将被截断。此外,您的保存函数正在返回指向已销毁对象的数据,调用 undefined behavior

    【讨论】:

    • 感谢您的评论。您能否详细说明“指向被破坏对象的数据”?我假设函数结束时数据被破坏。所以我在函数结束之前返回了 const char * 数据并将其存储在 save() 外部的变量中,然后将其传递给 load()。由于程序错误,我猜我的逻辑是错误的。
    • std::string::data()返回的指针只有在string被修改或销毁后才有效。 std::stringstream::str() 返回的 stringreturn 语句完成后被销毁。因此,无论谁调用您的 save 函数,都会 100% 获得指向无效数据的指针。
    • 啊,我明白了。您能否推荐一种更好的方法或在不嵌入空值的情况下传递数据的方法?
    • @user459811 :二进制数据将嵌入空值。关键点是使用在嵌入空值时不会截断数据的数据结构来传递数据。 std::vector&lt;char&gt; 是显而易见的候选者,尽管从技术上讲,std::string 只要您不使用其 datac_str 方法就可以正常工作。
    • @user459811 : std::string::size() 是准确的,与嵌入的空值无关,与std::vector&lt;unsigned char&gt;::size() 完全相同。无论如何,如果你真的想要,给定std::string str,你可以构造一个std::vector&lt;unsigned char&gt;,如下所示:std::vector&lt;unsigned char&gt; vec(str.begin(), str.end());
    【解决方案2】:

    您不能将 binary_iarchive/binary_oarchive 与 stringstream 一起使用,因为“字符串”中不允许使用某些“二进制”字符。如果要使用 stringstream,则需要 'text_iarchive/text_oarchive' 或 'xml_iarchive/xml_oarchive'。

    对于“binary_{io}archive”(性能),您必须使用“fstream”。

    【讨论】:

    • 感谢您的评论。我已经编辑了我的代码,使其不再使用字符串,而是使用 const char *,这样我仍然可以使用字符串流。但是,它仍然给我错误。非常感谢正确方向的任何一点。谢谢。
    • std::strings 中确实允许使用“二进制”字符。跟我说吧——charcharchar,除了上下文之外,“二进制”和“文本”没有区别。
    猜你喜欢
    • 2020-06-15
    • 2020-10-01
    • 2015-06-14
    • 2012-02-03
    • 2017-04-15
    • 2021-07-31
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多