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

标签 c++ boost boost-serialization

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

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

我尝试从 Book 类的序列化方法(文档示例中所做的)中删除 ar & name,这也导致了输入流错误。

调试时,我发现在 load_primitive` 函数的 load _access 类中引发了异常。

源代码(1)

#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

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

最佳答案

save_construct_data()load_construct_data() 应该一起工作,但在您的代码中,save_construct_data() 永远不会被调用。发生这种情况是因为它的签名不正确:Book* 应该是 const Book*

然后,您会收到流错误,因为序列化和反序列化彼此不一致 - 序列化在 serialize() 中写入一次 Book::name,但反序列化会尝试在 load_construct_data()serialize() 中读取两次。

完整的工作示例(main() 未更改,除了删除 std::ios::binary):

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 命名空间中定义的,除了与 boost::serialization 建立友好关系之外,您还需要为该函数添加一个 friend 声明::访问。文档中没有提到这一点,但如果没有 friend 声明,代码将无法编译。

关于c++ - 使用 boost 反序列化时输入流错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76889919/

相关文章:

c++ - 使用 CMake 设置 C++ 目标文件输出位置

c++ - 将 boost::variant 传递给(来自)dll 是否安全?

C++ Boost TCP channel 上的序列化对象,双向通信不起作用

c++ - 将反序列化 boost 为动态类型

c++ - RAII 和推导的模板参数

C++ 模板特化冗余减少

c++ - 在分析 boost::graph 时,是否对顶点和边描述符或它们的迭代器进行操作?

c++ - 分配给指向 std::list 类型的共享指针不起作用

c++ - 为什么派生类的大小包括来自基类的私有(private)成员?

c++ - 变量隐藏在 Boost Phoenix 的嵌套 let block 中