C++ C++;在文件中存储对象
我有一个对象列表,我想存储在一个尽可能小的文件中,以便以后检索。我一直在仔细阅读,并开始(我认为)理解,但有几个问题。以下是我正在处理的代码片段:C++ C++;在文件中存储对象,c++,object,binary,storage,fstream,C++,Object,Binary,Storage,Fstream,我有一个对象列表,我想存储在一个尽可能小的文件中,以便以后检索。我一直在仔细阅读,并开始(我认为)理解,但有几个问题。以下是我正在处理的代码片段: static bool writeHistory(string fileName) { fstream historyFile; historyFile.open(fileName.c_str(), ios::binary); if (historyFile.good()) { list<
static bool writeHistory(string fileName)
{
fstream historyFile;
historyFile.open(fileName.c_str(), ios::binary);
if (historyFile.good())
{
list<Referral>::iterator i;
for(i = AllReferrals.begin();
i != AllReferrals.end();
i++)
{
historyFile.write((char*)&(*i),sizeof(Referral));
}
return true;
} else return false;
}
摘自教程。现在我相信它正在做的是将对象转换为指针,获取值和大小并将其写入文件。但是如果它这样做了,为什么还要费心做转换呢?为什么不从头开始计算呢?为什么它需要这个尺寸?此外,据我当时的理解,为何
historyFile.write((char*)i,sizeof(Referral));
不编译?我是一个迭代器(迭代器不是指针吗?)。或者干脆
historyFile.write(i,sizeof(Referral));
我为什么要乱搞地址呢?我不是在文件中存储数据吗?如果地址/值是自己持久化的,为什么我不能将删除的地址存储在纯文本中,然后再获取它们的值呢
我还应该使用.txt扩展名吗抱歉,有这么多小问题,但基本上都归结为如何有效地将对象存储在文件中?Fstream.write只将原始数据写入文件。第一个参数是指向数据起始地址的指针。第二个参数是对象的长度(以字节为单位),因此write知道要写入多少字节
file.write((char*)&object,sizeof(className));
^
此行将对象的地址转换为字符指针
historyFile.write((char*)i,sizeof(Referral));
^
此行试图将对象(i)转换为字符指针(无效)
^
此行正在传递write对象,但它需要一个char指针。您尝试执行的操作(向文件中读取和写入原始内存)将调用未定义的行为,将中断任何非纯旧数据类型的操作,并且生成的文件将依赖于平台,编译器依赖,甚至可能依赖于编译器设置
historyFile.write((char*)i,sizeof(Referral));
C++没有任何内置的序列化复杂数据的方法。但是,您可能会发现有些库很有用。例如:
问题1为什么。。。不编译?
答:因为我不是推荐人*——它是一个列表::迭代器;;迭代器是指针的抽象,但它不是指针
问题#2我是否仍应使用.txt扩展名?
回答:可能不会。txt由许多系统与MIME类型text/plain关联
未问的问题:这有用吗?
回答:如果推荐信上有任何指针,否。当您尝试从文件中读取引用时,指针将指向内存中某个曾经存在的位置,但不能保证那里有任何有效的内容,尤其是指针最初指向的内容。小心。您尝试执行的操作称为序列化。Boost有这样做的理由 在某些情况下,在一些非常重要的条件下,您尝试做的事情可以起作用。它只适用于类型。它只保证对使用相同版本的编译器和相同参数编译的代码有效
(字符*)和(*i)
表示取迭代器i,解引用它以获取对象,取其地址并将其视为字符数组。这是写入文件的开始sizeof(reference)
是将被写入的字节数
不,迭代器不一定是指针,尽管指针满足迭代器的所有要求 您已经看过了吗,它很健壮,有很好的文档,支持版本控制,如果您想切换到XML格式而不是二进制格式,那么会更容易 迭代器不是指针吗 迭代器的作用类似于外部的指针。在大多数(也许所有)情况下,它实际上是某种形式的对象,而不是一个简单的指针。迭代器可能包含一个指针作为内部成员变量,用于执行其工作,但如果需要,它也可能包含其他变量或附加变量 此外,即使迭代器内部有一个简单的指针,它也可能不会直接指向您感兴趣的对象。它可能指向容器类使用的某种簿记组件,然后可以使用该组件获取实际的感兴趣对象。幸运的是,我们不需要关心这些内部细节到底是什么 考虑到这一点,下面是在
(char*)&(*i)
中发生的事情
返回对列表中存储的对象的引用*i
获取该对象的地址,从而生成指向该对象的指针&
将该对象指针强制转换为char指针(char*)
Referral& r = *i;
Referral* pr = &r;
char* pc = (char*)pr;
我为什么要胡闹 还有地址吗 为什么它需要这个尺寸
fstream::write
设计用于将一系列字节写入文件。它不知道这些字节意味着什么。给它一个地址,这样它就可以从地址指向的任何地方开始写入存在的字节。您给它一个大小,以便它知道要写入多少字节
file.write((char*)&object,sizeof(className));
因此,如果我这样做:
MyClass ExampleObject;
file.write((char*)ExampleObject, sizeof(ExampleObject));
然后它将直接存在于ExampleObject
中的所有字节写入文件
注意:正如其他人所提到的,如果要编写的对象具有动态分配内存或以其他方式使用指针的成员,则