C ++将数据字节解析为struct

时间:2013-03-26 07:13:47

标签: c++ visual-c++

我是新来的,我有一个问题 我有一个结构,假设整体大小为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;
    }

但它失败了,返回的无效数据超出了我的预期(我可以确定,这不是文件错误,文件结构正确)

有人能帮助我吗? 感谢

4 个答案:

答案 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语句指示返回默认设置。您可能需要使用pushpop说明(请参阅enter link description here) - 但这不是必需的。

其次,更重要的是,您不应该使用像8这样的硬代码值。始终使用sizeof来读取或写入结构。此外,绝对不需要此声明:

char* buffer = new char[8];
...

只需声明Header变量本身,然后继续阅读:

Header header;
...
fs.read(&header, sizeof(Header));