【问题标题】:Boost Serialization multiple objectsBoost序列化多个对象
【发布时间】:2011-06-25 19:12:00
【问题描述】:

我正在使用二进制序列化一个带有 boost 的类。我正在使用 ios::append 以继续将多个对象附加到该文件中。如何检索所有存储的对象?

这是我的测试类,它尝试多次序列化并检索它们。我已经评论了我没有得到正确数据的故障点。

using namespace std;
 class Data {
 public:
double get_latitude() const {
    return _latitude;
}

double get_longitude() const {
    return _longitude;
}

void set_latitude(double _latitude) {
    this->_latitude = _latitude;
}

void set_longitude(double _longitude) {
    this->_longitude = _longitude;
}
private:
double _latitude;
double _longitude;
friend class boost::serialization::access;
// When the class Archive corresponds to an output archive, the
// & operator is defined similar to <<.  Likewise, when the class Archive
// is a type of input archive the & operator is defined similar to >>.
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
    ar & _latitude;
    ar & _longitude;
}
};

class DataTest: public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE( DataTest);
CPPUNIT_TEST(testMultipleSaveData);
CPPUNIT_TEST_SUITE_END();

public:

void testMultipleSaveData() {
    Data data;
    data.set_latitude(1.0);
    data.set_longitude(2.0);
    saveData(data);
    Data secondData;
    secondData.set_latitude(5.0);
    secondData.set_longitude(6.0);
    saveData(secondData);
    Data returnData;
    Data return2Data;
    {
        // create and open an archive for input
        std::ifstream ifs("data.dat", ios::binary);
        boost::archive::binary_iarchive ia(ifs);
        // read class state from archive
        ia >> returnData;
        ia >> return2Data;
        // archive and stream closed when destructors are called
    }
    CPPUNIT_ASSERT_EQUAL(data.get_latitude(), returnData.get_latitude());
    CPPUNIT_ASSERT_EQUAL(data.get_longitude(), returnData.get_longitude());
    //Failure on next line
    CPPUNIT_ASSERT_EQUAL(secondData.get_latitude(), return2Data.get_latitude());
    CPPUNIT_ASSERT_EQUAL(secondData.get_longitude(), return2Data.get_longitude());
}

void saveData(Data data) {
    std::ofstream ofs("data.dat", ios::binary | ios::app);
    boost::archive::binary_oarchive oa(ofs);
    oa << data;
}

 };
 CPPUNIT_TEST_SUITE_REGISTRATION( DataTest);

【问题讨论】:

    标签: c++ serialization boost


    【解决方案1】:

    决定添加另一个答案以避免完全混乱。

    您的问题是您序列化为boost::archive::binary_oarchive 的单独实例。 Boost Archive 在文件开头存储了一些内部信息(我不会称它为标题,因为 Boost Serialization 有单独的标题来存储版本号),然后您会收到此信息的两个副本,位于文件开头和数据序列化之间。

    Boost Archive 不是为此类用途而设计的。甚至指定boost::archive::no_header 如下:

    boost::archive::text_oarchive oa(ofs, boost::archive::no_header);
    

    没有帮助,因为此选项配置了另一个包含版本号的标头。您需要序列化到 Boost Archive 的同一实例。

    【讨论】:

    • 那么有没有一种简单的方法可以更改它以使其工作,或者您认为 Boost Serialization 不是我要求的正确选择?
    • 正如我所写,您需要序列化到 Boost Archive 的同一个实例。打开它 -> 序列化 所有 对象 -> 关闭它。
    • downvoter 可以解释原因吗? 6天后否决接受的答案?这只是某种仇杀吗?
    【解决方案2】:

    1) 如果存储的对象数量是恒定的 - 以存储它们的相同顺序加载它们:

    存储:

    std::ofstream ofs(FILENAME, ios::app);
    boost::archive::text_oarchive oa(ofs);
    oa << data1 << data2 << ... << data_n;
    

    正在加载:

    std::ifstream ifs(FILENAME);
    boost::archive::text_iarchive ia(ifs);
    ia >> data1 >> data2 >> ... >> data_n;
    

    2) 如果存储的对象数量可以变化 - 序列化数字:

    存储:

    std::ofstream ofs(FILENAME, ios::app);
    boost::archive::text_oarchive oa(ofs);
    oa << number_of_objects;
    for (size_t i = 0; i != number_of_objects; ++i)
        oa << data[i];
    

    正在加载:

    std::ifstream ifs(FILENAME);
    boost::archive::text_iarchive ia(ifs);
    size_t number_of_objects;
    ia >> number_of_objects;
    // allocate number_of_objects objects
    for (size_t i = 0; i != number_of_objects; ++i)
        ia >> data[i];
    

    [编辑] 考虑到您编辑的问题:
    首先,您将binary_archive 与文本模式文件一起使用!您需要使用 std::ios::binary 标志打开文件(用于读取和写入)。这是一个错误,可能是您的问题的原因(“可能”是因为我们看不到您的确切序列化实现)。

    我无法编译您的代码,因为它不完整。尝试在这个简单的示例中实现带有序列化的简单类并存储/加载 2 个对象,以便轻松找出更复杂情况的问题

    [EDIT2] 您是否从 Boost.Serialization 示例中获取了binary_archive?如果是这样,请注意它不是便携式的,我不知道这对您是否重要

    【讨论】:

    • 如果我要同时保存所有对象,那确实有效。我将每秒序列化一个新对象。所以它会创建一个新行,并且在加载时它不起作用。它只加载第一个。有什么想法吗?
    • 无论您序列化的频率或数量如何。请提供一个简化但完整的示例,以便我们准确指出问题所在
    • 好的,我在原始帖子中添加了更多信息。感谢您的宝贵时间。
    • 我已在测试类中使用完整示例更新了代码示例。再次感谢您的帮助。
    【解决方案3】:

    如果您想阅读多个,请告诉它加载多个。序列化只有在您明确告知或通过序列化对象容器时才知道加载多个对象。

    【讨论】:

      猜你喜欢
      • 2015-10-08
      • 2018-07-20
      • 2013-05-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2013-04-15
      相关资源
      最近更新 更多