将对象信息保存到二进制文件中

saving object information into a binary file

本文关键字:二进制文件 保存 对象 信息      更新时间:2023-10-16

我正在尝试将对象的所有成员变量保存在二进制文件中。但是,成员变量是动态分配的向量。那么,有没有办法合并所有数据并将其保存在二进制文件中。截至目前,它只是保存指针,这几乎没有帮助。以下是我的运行代码。

#include <vector>
#include <iostream>
#include <fstream>
class BaseSaveFile {
protected:
std::vector<float> first_vector;
public:
void fill_vector(std::vector<float> fill) {
first_vector = fill;
}
void show_vector() {
for ( auto x: first_vector )
std::cout << x << std::endl;
}
};

class DerivedSaveFile : public BaseSaveFile {

};

int main ( int argc, char **argv) {
DerivedSaveFile derived;
std::vector<float> fill;
for ( auto i = 0; i < 10; i++) {
fill.push_back(i);
}
derived.fill_vector(fill);
derived.show_vector();
std::ofstream save_object("../save_object.bin", std::ios::out | std::ios::binary);
save_object.write((char*)&derived, sizeof(derived));
}

目前二进制文件的大小仅为 24 字节。但是由于 10 个浮点数的矢量,我的输出要大得多。

">

有没有办法合并所有数据并将其保存在二进制文件中" - 当然有。您编写代码来迭代所有数据,并将其转换为适合写入文件的形式(您知道以后在读回文件时如何解析(。然后编写代码来读取文件,将其分析为有意义的变量类,并从读入数据构造新对象。它没有内置的功能,但它不是火箭科学 - 只是你需要做的一堆工作/代码。

顺便说一句,这称为序列化/反序列化,如果您想使用首选搜索引擎查找更多详细信息。

问题

您可以将对象的确切二进制内容写入文件:

save_object.write((char*)&derived, sizeof(derived));

但是,不能保证通过反向读取操作将其读回内存。这仅适用于具有简单可复制类型且不包含任何指针的一小部分对象。

您可以使用std::is_trivially_copyable<BaseSaveFile>::value验证您的类型是否与此定义匹配,但我已经可以告诉您这不是因为向量。

为了简化正式定义,平凡可复制类型或多或少是由其他平凡可复制的元素和非常基本的数据类型(如 int、float、char 或固定大小的数组(组成的类型。

解决方案:序列化简介

常规解决方案,如它称为序列化的另一个响应中所述。但对于更量身定制的答案,以下是它的样子。

您可以将以下公共方法添加到您的类型中:

std::ostream& save(std::ostream& os){
size_t vsize=first_vector.size(); 
os.write((char*)&vsize, sizeof(vsize));
os.write((char*)first_vector.data(), vsize*sizeof(float)); 
return os; 
}

此方法有权访问所有成员,并可以将它们写入磁盘。 对于向量的情况,您首先要记下它的大小(以便稍后读取文件时知道它有多大(。

然后,您将添加相反的方法:

std::istream& load(std::istream& is){
size_t vsize; 
if(is.read((char*)&vsize, sizeof(vsize))) {
first_vector.resize(vsize);
is.read((char*)first_vector.data(), vsize*sizeof(float)); 
}
return is; 
}

这里的诀窍是首先读取磁盘上矢量的大小,然后在加载之前调整矢量的大小。

请注意istreamostream的使用。 这允许您将数据存储在文件中,但如果需要,您可以使用任何其他类型的流,例如内存字符串流。

这是一个完整的在线示例(它使用stringstream,因为在线服务不提供要写入的文件(。

更多序列化 ?

有一些序列化技巧需要了解。 首先,如果您有派生类型,则需要将load()save()设为虚拟,并为派生类型提供其自己的重写版本。

如果某个数据成员不可简单复制,则需要自己的load()save(),然后您可以递归调用。 或者你需要自己处理这件事,这只有在你可以访问恢复其状态所需的所有成员时才有可能。

最后,你不需要重新发明轮子。 外面有一些库可能会有所帮助,例如提升序列化或谷物