我是新来的,我有一个问题 我有一个结构,假设整体大小为8字节,这里是struct:
struct Header
{
int ID; // 4 bytes
char Title [4]; // 4 bytes too
}; // so it 8 bytes right?
我有一个8字节的文件...... 我只想问一下,如何将该文件的数据解析为
的结构我试过这个:
Header* ParseHeader(char* filename)
{
char* buffer = new char[8];
fstream fs(filename);
if (fs.is_open() != true)
throw new exception("Couldn't Open file for Parsing Header.");
fs.read(buffer, 8);
if (!fs)
{
delete[] buffer;
throw new exception("Couldn't Read header OJN file.\nHeader data was corrupted");
}
Header* header = (Header*)((void*)buffer);
delete[] buffer;
fs.close();
return header;
}
但它失败了,返回的无效数据超出了我的预期(我可以确定,这不是文件错误,文件结构正确)
有人能帮助我吗? 感谢
答案 0 :(得分:1)
看起来你在这一点上做得很好:
Header* header = (Header*)((void*)buffer);
delete[] buffer;
fs.close();
注意您在转换后删除了缓冲区,这意味着标题指向已删除的位置 - >垃圾,如果你还想使用它,你需要不删除或复制数据。
另外,说实话,我不明白你的代码如何编译,你的函数声明它返回一个Header,而你返回一个Header * ..
答案 1 :(得分:0)
您正在删除正在返回的数据。因此,无法再访问header
。
我认为你的意思是:
Header header = *(Header*)((void*)buffer);
这实际上会复制标题。
答案 2 :(得分:0)
只要涉及C ++,您的8字节文件正确映射到struct Header
这一事实仅仅是运气。该结构可能具有内部填充,使其大于8个字节,并且数据字节顺序可能在您的文件和CPU之间有所不同。
我意识到您的代码可以使用您的特定编译器版本,您的操作系统以及您的CPU ,但您不应该进入像这样编码的习惯,否则一旦你改变了这些参数(或者甚至只是一些编译器标志),你可能会遇到大麻烦。换句话说,你正在做的是非常糟糕的做法。在C ++中,您甚至不能保证int
实际上是4个字节。
从文件加载此类二进制数据的Right Way™是单独加载每个字段,并根据您使用的CPU(例如,通过hton* / ntoh*
或类似功能)确保正确的字节顺序转换。使用像int32_t
这样的固定大小类型也有帮助。
答案 3 :(得分:0)
只需将您的结构定义为1字节边界:
#pragma pack(1)
struct Header
{
int ID; // 4 bytes
char Title [4]; // 4 bytes too
};
#pragma pack()
第一个pack
语句指示编译器对结构中的成员使用单字节填充。这样Header
的大小将为8个字节。第二个pack
语句指示返回默认设置。您可能需要使用push
和pop
说明(请参阅enter link description here) - 但这不是必需的。
其次,更重要的是,您不应该使用像8
这样的硬代码值。始终使用sizeof
来读取或写入结构。此外,绝对不需要此声明:
char* buffer = new char[8];
...
只需声明Header
变量本身,然后继续阅读:
Header header;
...
fs.read(&header, sizeof(Header));