如何用Boost XML序列化将类集合保存至独立二进制文件?
实现Boost序列化中集合的外部文件存储
要实现你想要的「将集合单独保存到二进制文件,XML中存储该文件路径」的需求,Boost序列化本身没有内置的<EXT_BINARY_FILE>操作,但我们可以通过扩展序列化逻辑手动实现这个功能。核心思路是区分XML归档类型,在序列化时将集合写入外部文件并记录路径,反序列化时读取路径并加载外部文件内容。
以下是完整的实现方案:
1. 修改类结构与序列化逻辑
首先给MyClass添加一个存储外部二进制文件路径的成员(用mutable修饰,方便在const上下文中修改),然后扩展serialize模板函数,添加外部文件的读写逻辑:
#include <boost/serialization/serialization.hpp> #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_iarchive.hpp> #include <boost/serialization/is_xml_archive.hpp> #include <boost/serialization/vector.hpp> #include <filesystem> #include <fstream> #include <string> #include <stdexcept> namespace fs = std::filesystem; class MyClass { public: static void Save(const MyClass& inst, const std::string& filename); static void Load(MyClass& inst, const std::string& filename); private: int a = 0; std::vector<int> b; mutable std::string m_binary_path; // 存储外部二进制文件路径 friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version) { // 序列化普通成员a ar & BOOST_SERIALIZATION_NVP(a); const bool is_xml = boost::serialization::is_xml_archive<Archive>::value; std::string binary_path; if constexpr (boost::serialization::is_saving<Archive>::value) { binary_path = m_binary_path; // 仅XML归档时,将集合写入外部二进制文件 if (is_xml && !binary_path.empty()) { std::ofstream bin_file(binary_path, std::ios::binary); if (!bin_file.is_open()) { throw std::runtime_error("无法打开二进制文件进行写入: " + binary_path); } boost::archive::binary_oarchive bin_ar(bin_file); bin_ar & b; // 将集合b序列化到二进制文件 } // 把二进制文件路径存入XML归档 ar & BOOST_SERIALIZATION_NVP(binary_path); } else { // 加载时先读取二进制文件路径 ar & BOOST_SERIALIZATION_NVP(binary_path); if (is_xml && !binary_path.empty()) { std::ifstream bin_file(binary_path, std::ios::binary); if (!bin_file.is_open()) { throw std::runtime_error("无法打开二进制文件进行读取: " + binary_path); } boost::archive::binary_iarchive bin_ar(bin_file); bin_ar & b; // 从二进制文件反序列化集合b } else { // 非XML归档时直接序列化集合(兼容其他归档类型) ar & BOOST_SERIALIZATION_NVP(b); } } } };
2. 实现Save和Load静态方法
在Save方法中,我们根据XML文件路径生成对应的二进制文件路径(比如同目录下的c.dat),设置到类成员后再执行XML序列化:
void MyClass::Save(const MyClass& inst, const std::string& filename) { MyClass temp_inst = inst; fs::path xml_path(filename); // 生成二进制文件路径:与XML文件同目录,文件名为c.dat temp_inst.m_binary_path = (xml_path.parent_path() / "c.dat").string(); std::ofstream xml_file(filename); if (!xml_file.is_open()) { throw std::runtime_error("无法打开XML文件进行写入: " + filename); } boost::archive::xml_oarchive xml_ar(xml_file); xml_ar << BOOST_SERIALIZATION_NVP(temp_inst); } void MyClass::Load(MyClass& inst, const std::string& filename) { std::ifstream xml_file(filename); if (!xml_file.is_open()) { throw std::runtime_error("无法打开XML文件进行读取: " + filename); } boost::archive::xml_iarchive xml_ar(xml_file); xml_ar >> BOOST_SERIALIZATION_NVP(inst); }
3. 关键逻辑说明
- 归档类型判断:通过
boost::serialization::is_xml_archive区分当前是否为XML归档,仅在XML归档时处理外部文件,同时兼容其他归档类型(比如直接二进制归档)。 - 路径处理:用
std::filesystem(C++17及以上)管理文件路径,确保二进制文件与XML文件处于同一目录,避免路径混乱。 - 异常处理:添加了文件打开失败的异常抛出,方便调试和错误捕获(你可以根据需求调整为返回错误码等方式)。
- 灵活性:如果需要自定义二进制文件名,只需修改
Save方法中生成路径的逻辑,比如基于XML文件名生成唯一的二进制文件名(如myclass_c.dat)。
最终生成的文件结构
执行Save方法后,会在XML文件所在目录生成两个文件:
myclass.xml:包含a的值和binary_path(即c.dat的相对路径)c.dat:存储std::vector<int> b的二进制序列化数据
内容的提问来源于stack exchange,提问作者Eric David
相关产品推荐
相关产品推荐

