C++如何实现boost::property_tree::ptree的二进制文件读写
实现逻辑
boost::property_tree::ptree 没有原生二进制序列化接口,我们通过递归遍历节点实现通用读写,每个节点存储3部分信息:
- 节点自身存储的字符串值(ptree内部所有类型值均以字符串形式存储,读取时自动适配类型转换)
- 子节点总数量
- 逐个存储每个子节点的键名、子节点的完整数据
注意:操作前请确认你的
std::ofstream/std::ifstream是通过std::ios::binary标志打开,否则二进制数据会被转义导致读写失败。
以下代码默认你已实现基础类型的二进制读写接口,可直接替换为你项目中已有的同功能接口:
// 你项目中已实现的基础读写接口示例,替换为实际接口即可 void WriteString(std::ofstream& _file, const std::string& str); void WriteUint32(std::ofstream& _file, uint32_t num); std::string ReadString(std::ifstream& _file); uint32_t ReadUint32(std::ifstream& _file);
完整接口实现
void TGS_File::PTreeToFile(std::ofstream &_file, boost::property_tree::ptree _data) { // 写入当前节点值 WriteString(_file, _data.data()); // 写入子节点数量 uint32_t child_cnt = static_cast<uint32_t>(_data.size()); WriteUint32(_file, child_cnt); // 遍历写入所有子节点 for (auto& node_item : _data) { WriteString(_file, node_item.first); PTreeToFile(_file, node_item.second); } } boost::property_tree::ptree TGS_File::PTreeFromFile(std::ifstream &_file) { boost::property_tree::ptree _data; // 读取当前节点值 _data.data() = ReadString(_file); // 读取子节点数量 uint32_t child_cnt = ReadUint32(_file); // 逐个读取子节点并插入 for (uint32_t i = 0; i < child_cnt; ++i) { std::string key = ReadString(_file); auto child_node = PTreeFromFile(_file); _data.add_child(key, child_node); } return _data; }
注意事项
- 该实现不依赖ptree的具体结构,无需提前知晓键值定义即可完成全量序列化/反序列化
- 读写完成后文件指针会自动停在ptree数据块末尾,不影响
.tgasset文件中其他自定义数据的读写 - 如果需要跨平台使用,请注意处理基础类型读写的大小端字节序问题,同平台使用可忽略
- 如果你的ptree层级超过千级,建议将递归逻辑改为迭代式的广度/深度优先遍历,避免栈溢出
- 从xml/json等格式转换得到的ptree(含
<xmlattr>这类属性节点)可正常被序列化还原
内容的提问来源于stack exchange,提问作者BDC_Patrick
相关产品推荐
相关产品推荐

