我需要将结构中包含的数据写入二进制文件。
让我们说给出
的结构struct data {
unsigned char sig;
int reserved;
}
我希望能够简单地将此结构的内容输出到文件中。
我试过用这个
fstream out("C:\\somepath", ios::out | ios::app | ios::binary);
data writedata;
writedata.sig = 'BM';
writedata.reserved = NULL;
out.write((char*)&writedata, sizeof(writedata));
out.close();
我预计输出会是(十六进制,使用32位编译器(所以整数是4个字节)):
42 4D 00 00 00 00
但这不是印刷品。
有人可以解释为什么这不起作用以及修复它所需的步骤吗?
感谢。
答案 0 :(得分:2)
首先,'BM'
是两个字节,并且不能适合单个unsigned char
('BM'
可能被编译器视为多字节文字,这可能不是什么你想要的。)
然后,编译器可以自由地在结构中添加填充以使其与正确的字边界对齐;在x86上,正确的成员aligment保证了更好的读取性能,在其他架构上如果对齐错误则会出现硬件异常。
在您的情况下,例如,在32位x86上,结构的二进制布局将是sig
的一个字节,三个字节的填充,然后是reserved
int
(它将在4字节边界上对齐以获得最佳访问速度)。
没有标准的方法可以避免填充;你必须采用特定于编译器的技巧。在VC ++上,你必须使用#pragma pack
,也支持g ++和clang,尽管它们的“原生”方式是使用__attribute__(packed)
。
顺便说一句,如果你必须将“可移植”文件格式写入文件(就像你想写的DIB一样),总是使用固定大小的整数类型(来自stdint.h
)并准备好处理如果您计划移植到其他架构,则会出现字节序问题。
答案 1 :(得分:0)
我看到编译器错误/警告:
;
的定义末尾缺少data
。'BM'
是错误的。它需要是单一字符。将NULL
分配给data.reserved
。你应该做到:
data.reserved = 0;
如果要最小化磁盘上文件占用的空间,请分别编写结构的每个字段。
out.write((char*)&writedata.sig, sizeof(writedata.sig));
out.write((char*)&writedata.reserved, sizeof(writedata.reserved));
我注意到的另一件事是您使用标记ios::app
打开文件。它附加到现有文件。你是这个意思吗?如果没有,您可以删除该标志。