提升序列化多个对象

时间:2011-02-11 20:02:36

标签: c++ serialization 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);

3 个答案:

答案 0 :(得分:8)

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

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

Boost Archive 并非专为此类用途而设计。甚至指定boost::archive::no_header,如:

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

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

答案 1 :(得分: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吗?如果是这样,请注意它不便携,我不知道这对你来说是否重要

答案 2 :(得分:1)

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