二进制读取和编写复杂的c++结构
binary reading and writing complicated stucts in c++
我需要在我的项目中保存/读取我的数据结构的能力,但所有的数据都是相当复杂和独特的结构本身的形式,我通常通过其他结构和向量实现。我把它们都包装成一个结构体这样我就有了像
这样的东西struct master{
std::vector<apprentice_type1> a;
std::vector<apprentice_type2> b; //etc.
std::string label;
};
与其他定义如
struct apprentice_type1{
vec location;
int point_label;
std::vector<int> relational_data;
};
struct vec{
double x,y,z;
};
所以它变得非常复杂!我拼命地想要一些像
这样的美好,快速和天真的东西master obj;
//write to obj....
std::ofstream ofs("data.dat", std::ios::binary);
ofs.write((char *)&obj, sizeof(obj));
可能会起作用,但目前似乎不起作用。在我迷失在调试的兔子洞之前,这真的是可能的吗?我接近它的方式,还是我需要重新考虑?如果有,怎么做?
谢谢。
如果您想要一个Boost序列化的替代方案,并且可以访问c++ 11编译器,您也可以查看一下cereal。它的工作方式与Boost序列化几乎相同,但它只是一个头文件库,所以没有什么可链接的
[…还是我需要重新考虑?如果有,怎么做?
你可能需要提供一个完整的实现(即探索"兔子洞")。
这是一个已知的问题(流序列化),并且没有单一的最佳解决方案,因为大多数实现需要解决不同的需求。
你可以这样做:
-
实现std::i/ostream序列化;这意味着你将复习你的类并实现
operator>>(std::istream*, your_type&)
和它的逆operator<<(std::ostream*, your_type&)
。 -
实现基于流库的序列化(如boost.archive)
使用JSON或XML库。 使用google协议缓冲区(或其他)
根据您的需要滚动您自己的实现。
如果您选择boost::序列化,这里有一个小示例:
#include <fstream>
#include <vector>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/vector.hpp>
template <typename T>
inline const boost::serialization::nvp<T> archive_value(const char* name, T& value) {
return boost::serialization::make_nvp(name, value);
}
const unsigned Version = 0;
class Point{
public:
double x,y,z;
private:
template <typename P, typename Archive>
static void serialize(P& p, Archive& ar, const unsigned int version) {
std::cout << "Pointn";
ar & archive_value("X", p.x);
ar & archive_value("Y", p.y);
ar & archive_value("Z", p.z);
}
public:
template <typename Archive>
void serialize(Archive& ar, const unsigned int version) const {
serialize(*this, ar, version);
}
template <typename Archive>
void serialize(Archive& ar, const unsigned int version) {
serialize(*this, ar, version);
}
};
BOOST_CLASS_VERSION(Point, Version)
struct Scene{
std::vector<Point> points;
private:
template <typename S, typename Archive>
static void serialize(S& s, Archive& ar, const unsigned int version) {
std::cout << "Scenen";
ar & archive_value("Points", s.points);
}
public:
template <typename Archive>
void serialize(Archive& ar, const unsigned int version) const {
serialize(*this, ar, version);
}
template <typename Archive>
void serialize(Archive& ar, const unsigned int version) {
serialize(*this, ar, version);
}
};
BOOST_CLASS_VERSION(Scene, Version)
template <typename Archive>
void register_types(Archive& ar) {
ar.template register_type<Point>();
ar.template register_type<Scene>();
}
int main() {
Scene scene;
scene.points = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 } };
// Output
{
std::ofstream out("test.dat", std::ios_base::binary);
boost::archive::binary_oarchive output(out);
// First the version!
output & archive_value("Version", Version);
// Next the types!
register_types(output);
// Finally the data
output & archive_value("Scene", scene);
}
scene.points = {};
// Input
{
int version;
std::ifstream in("test.dat", std::ios_base::binary);
boost::archive::binary_iarchive input(in);
// First the version!
input & archive_value("Version", Version);
// Next the types!
register_types(input);
// Finally the data
input & archive_value("Scene", scene);
}
for(const auto& p : scene.points)
std::cout << p.x << 'n';
}
注意:文件格式可能会发生变化,序列化函数(输入和/或输出)可能会根据文件版本进行调整。
相关文章:
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 如何重构类层次结构以避免菱形问题
- 如何在C++中序列化结构数据
- std::vector的包装器,使数组的结构看起来像结构的数组
- 没有为自己的结构调用列表推回方法
- 奇怪的结构&GCC&clang(void*返回类型)
- 在 c++ 中拥有一组结构的正确方法是什么?
- vscode g++链路故障:体系结构x86_64的未定义符号
- C++概念:如何使用'concept'检查模板化结构的属性?