【问题标题】:Reading and writing class objects to binary file读取和写入类对象到二进制文件
【发布时间】:2023-03-23 13:06:01
【问题描述】:

我想知道我写的时候会发生什么:

object.write((char*)&class_object, sizeof(class_object));
// or
object.read((char*)&class_object, sizeof(class_object));

从我目前阅读的内容来看,class_object 被转换为指针。但我不知道它是如何将对象携带的数据转换为二进制的。二进制实际上代表什么?

我是初学者。

编辑

您能否解释一下当我们编写上面的代码时到底发生了什么?我的意思是,当我们写 (char*)*S 时实际发生了什么,比如 S 是我声明的类的对象?

【问题讨论】:

标签: c++ serialization file-io binary-data


【解决方案1】:

这样想象一下,如果你将你的类转换为一个字符指针,类实例只是位于你的 RAM 中的一些内存块:

SomeClass someClassInstance;
char* data = reinterpret_cast<char*>(&someClassInstance);

它将指向您内存中的相同数据,但在您的程序中将被视为字节数组。

如果你把它转换回来:

SomeClass* instance = reinterpret_cast<SomeClass*>(data);

它将再次被视为类。

因此,为了将您的类写入文件并稍后重建它,您可以将data 写入某个大小为sizeof(SomeClass) 的文件,然后读取该文件并将原始字节转换为类实例。

但是,请记住,只有当您的班级是 POD(普通旧数据)时,您才能执行此操作!

【讨论】:

  • data 我的意思是指向原始字节的指针。通常是写入文件的原始字节。 data 将指向类实例所在的内存,要将其写入文件,您可以执行 ofstream.write(data, sizeof(SomeClass)); 之类的操作
  • 所以我们在技术上使用在内存位置移动的指针为我们写成二进制?
  • 恐怕我不明白你的问题,指针只是指向内存地址,每个地址都有一个字节。指针data 指向您的类实例的原始数据的开始。如果将指针data 加1,它将指向第二个字节。指针实际上只是一个数字,您可以对其进行加减。如果您取消引用指针,它将为您提供它指向的值。这样write 函数就能够将所有原始数据写入文件。它只会增加指针 n 倍,其中 n 是您的 sizeof(SomeClass) 以写入所有数据。
  • 很高兴它有帮助 ;-)
【解决方案2】:

在实践中,您的代码将无法工作并且可能会产生undefined behavior,至少当您的classstruct 不是POD(普通旧数据)并且包含指针或虚函数(还有一些vtable)。

二进制文件将包含您的对象的位表示,这不是portable 到另一台计算机,甚至不是运行同一程序的另一个进程(特别是因为ASLR),除非您的对象是 POD。

另请参阅this answer 以了解非常相似的问题。

你可能想要一些serialization。由于磁盘和文件访问比 CPU 慢很多(慢几十万),因此使用一些更便携的数据表示通常是明智的。实际上,您应该考虑一些文本表示,例如JSON, XML, YAML 等等......像jsoncpp 这样的库真的很容易使用,你需要编写一些代码来将你的对象转换为一些 JSON,并从一个 JSON。

还请记住,数据通常比代码更昂贵、更宝贵。关键是您经常希望一些旧数据(由程序的先前版本写入)被较新版本的程序读取。这可能不是微不足道的(例如,如果您在 class 中添加或更改了某些字段的类型)。

您还可以阅读有关dynamic software updating 的信息。这是一个有趣的研究课题。请注意databases

还可以阅读parsing 技术,尤其是recursive descent parsers。它们是相关的。

【讨论】:

  • 对,但我目前正在学校接受 c++ 培训
  • 谢谢,我不妨试试看。
猜你喜欢
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 2015-07-03
  • 2014-01-07
  • 2015-06-16
  • 1970-01-01
  • 2021-10-18
相关资源
最近更新 更多