将复杂的结构存储到文件中

时间:2013-06-09 00:25:18

标签: c++

我有以下课程

class WriterCollection
{
std::vector<Writer> arts;
public:
WriterCollection(void);
~WriterCollection(void);


void DisplayMenu();
void AddWriter();
void EditWriter();
void ShowWriterList();
int SearchWriter(std::string name = "");
};

我试图将其保存在二进制文件

所以我有

WriterCollection ac;
ac.AddWriter();
ac.AddWriter();
ac.AddWriter();

它会要求我为每位作家提供一个名字,我也可以为每一位作家添加一本书籍

我保存了它:

std::ofstream output_file("db.data", std::ios::binary);
output_file.write((char*)&ac, sizeof(ac));
output_file.close();

程序启动时我尝试阅读...

std::ifstream in( "db.data", std::ios::in );
if ( !in )
{
   std::cerr << "File could not be opened." << std::endl;
} 
in.read( reinterpret_cast< char * >( &ac ), sizeof( ac ) );

它正确地说我的收藏中有一个包含3个元素的向量,但它无法告诉我这些元素的数据......

任何人都可以帮我一把吗?

1 个答案:

答案 0 :(得分:2)

从不尝试将C ++类存储为二进制转储。

首先,std :: vector包含指向实际数据的指针和大小。你写的文件只是指针和大小;实际数据没有写入。读回数据后,指针指向内存中的某个位置,但该位置没有数据。

但即使您的数据都存储在一个地方,编写二进制转储仍然是个坏主意。如果您的类具有虚拟成员函数,则内存中的对象包含指向相应虚拟表的指针。无法保证下次运行程序时虚拟表将位于同一位置(可能在更改某些代码并重新编译之后)。更不用说当然如果你自己更改了类,你的二进制转储将不再适合新的类定义。

作为更一般的经验法则:除非您正在做低级别的事情(比如与设备接口),否则在代码中使用reinterpret_cast几乎总是表明您正在做一些您不应该做的事情

处理此问题的正确方法是遍历所有编写器对象并以明确定义的方式编写数据。数据格式是二进制还是文本格式取决于您(如果有疑问,请选择文本格式,如果只是因为它更容易调试)。但重要的是你不要盲目地转储内存数据,而是实际定义格式并确保数据以这种格式写入。