使用 boost 反序列化时输入流错误

问题描述 投票:0回答:1

我正在尝试使用 boost 序列化库来序列化一个类。序列化工作得很好,但是当我尝试读取写入文件的内容时,出现“输入错误”异常。

我阅读了 boost 序列化库的文档并提出了 (1) 了解如何使用非默认构造函数序列化和反序列化类。我试图尽可能接近文档中的示例。

我尝试从 Book 类的序列化方法(文档示例中所做的)中删除

ar & name
,这也导致了输入流错误。

调试时,我发现异常在 load_primitive` 函数的

load _access
类中抛出。

源代码(一)

#include <fstream>
#include <filesystem>

#include <boost/serialization/access.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class Book 
{
private:


    std::string name;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive& ar, const unsigned int file_version)
    {
        ar & name;
    }

public:

    Book(std::string name): name(name) {}

};

namespace boost {
namespace serialization {

    template<class Archive>
    inline void save_construct_data(Archive& ar, Book* book, const unsigned int file_version)
    {
        ar << book->name;
    }

    template<class Archive>
    inline void load_construct_data(Archive& ar, Book* book, const unsigned int file_version)
    {
        std::string name;
        ar >> name;
        ::new(book)Book(name);
    }
}
}

int main() 
{
    Book book("Harry Potter");

    std::ofstream ofs("Book.txt");
    boost::archive::text_oarchive oa(ofs);
    oa << &book;
    ofs.close();

    Book* read;
    std::ifstream ifs("Book.txt", std::ios::binary);
    boost::archive::text_iarchive ia(ifs);
    ia >> read;
    ifs.close();
}

我收到以下错误

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

提前感谢任何遮阳篷。 菲利克斯

c++ boost boost-serialization
1个回答
0
投票

save_construct_data()
load_construct_data()
应该一起工作,但在您的代码中
save_construct_data()
永远不会被调用。发生这种情况是因为它的签名不正确:
Book*
应该是
const Book*
。您会收到流错误,因为序列化和反序列化彼此不一致 - 序列化写入
Book::name
一次,但反序列化尝试读取它两次(您尝试在
Book::name
 中序列化/反序列化 
save_construct_data()
 两次) serialize()
)。

完整的工作示例(

main()
未更改):

class Book
{
    friend class boost::serialization::access;

private:
    std::string name;

    template<class Archive>
    void serialize(Archive&, unsigned int) { }

    template<class Archive>
    friend void save_construct_data(Archive& ar, const Book* book, unsigned int) {
        ar << book->name;
    }

    template<class Archive>
    friend void load_construct_data(Archive& ar, Book* book, unsigned int) {
        std::string name;
        ar >> name;
        ::new(book) Book(std::move(name));
    }

public:
    Book(std::string name): name(std::move(name)) { }
};

我在类中将

save_construct_data()
声明为
friend
以简化代码。由于某种原因,如果它定义在
boost::serialization
命名空间中,除了与
friend
友好之外,您还需要为该函数添加
boost::serialization::access
声明。文档中没有提到这一点,但如果没有
friend
声明,代码将无法编译。

© www.soinside.com 2019 - 2024. All rights reserved.