我有以下结构
struct MyStruct
{
int param1;
float param2;
double param3;
}
我可以使用
写入二进制文件fstream binary_file(file, ios::out|ios::binary);
binary_file.seekg(0, ios::beg);
binary_file.write((char *)aStruct,sizeof(MyStruct));
binary_file.close();
我可以使用
恢复它ifstream binary_file;
binary_file.open(file, ios::binary);
binary_file.seekg(0, ios::beg);
binary_file.read((char *)aStruct, sizeof(MyStruct));
binary_file.seekg (0, ios::end);
binary_file.close();
一切正常。现在将结构的定义更改为
struct MyStruct
{
int param1;
float param2;
double param3;
int paramA;
float paramB;
double paramC
}
问题是,如果我读取在定义更改之前写入的文件,param1,param2和param3将始终正确设置并且我可以确定paramA,paramB和paramC不会被分配任何垃圾吗?参数只会添加到结构的末尾。
根据reference ifstream读取函数应该在读取指定位数之前遇到eof时停止,所以希望这听起来很简单。我的测试也表明问题的答案是肯定的,但是我想确定你们,因为我一直在阅读二进制文件中的填充,并且完全不了解它是如何工作的。
答案 0 :(得分:4)
问题是,如果我读取在定义更改之前写入的文件,将始终正确设置param1,param2和param3
是的,你可以肯定的。
我可以确定paramA,paramB和paramC不会被分配任何垃圾吗?
这也是正确的,但有一点需要注意:除非这些字段在构造函数中初始化,否则在读取后它们将保持未初始化(即包含“垃圾”)。
最后,请注意,此技巧仅适用于从二进制文件中读取单个struct
。如果需要保存此类struct
的数组,则必须存储在写出数据时生效的sizeof
,否则您将无法对数组进行分区正确。
显然,即使没有在struct
的末尾添加新字段,也可以更改为不同的编译器或同一编译器的不同版本。
答案 1 :(得分:0)
这可能对您有用,也可能不适用。
如果编译器在添加新属性时更改了原始属性的填充,则无法读取原始值。
如果填充(和endian-ness)没有改变,那么你很可能能够在新属性中使用简单的未初始化数据从文件中成功恢复单个对象。