-1

我是新来的,我有一个问题,我有一个结构,假设总大小是 8 个字节,这里是结构:

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

4 回答 4

1

到目前为止,您似乎一切都很好:

Header* header = (Header*)((void*)buffer);
delete[] buffer;
fs.close();

请注意,您在转换后删除了缓冲区,这意味着标头指向已删除的位置-> 垃圾,如果您仍想使用它,则需要不删除或复制数据。

另外,老实说,我不明白你的代码是如何编译的,你的函数声明它返回一个 Header,而你返回一个 Header*..

于 2013-03-26T07:15:46.793 回答
0

您正在删除正在返回的数据。因此header不再可访问。

我认为您的意思是:

Header header = *(Header*)((void*)buffer);

这实际上将复制标题。

于 2013-03-26T07:15:48.690 回答
0

struct Header就涉及 C++ 而言,您的 8 字节文件正确映射到您的文件只是运气。该结构可能具有使其大于 8 个字节的内部填充,并且文件和 CPU 之间的数据字节序可能不同。

我意识到您的代码适用于您的特定编译器版本,在您的操作系统CPU上,但您不应该养成这样编码的习惯,否则一旦您更改任何这些参数,您可能会遇到大麻烦(或者甚至可能只是一些编译器标志)。换句话说,你正在做的是非常糟糕的做法。在 C++ 中,您甚至不能保证 anint实际上是 4 个字节。

从文件中加载此类二进制数据的正确方法是单独加载每个字段并确保根据您使用的 CPU(例如通过hton* / ntoh*或类似功能)进行正确的字节顺序转换。使用固定大小的类型int32_t也有帮助。

于 2013-03-26T08:02:32.307 回答
0

只需将 1 字节边界的结构定义为:

#pragma pack(1)
struct Header 
{
    int ID;             // 4 bytes
    char Title [4];     // 4 bytes too
};
#pragma pack()

第一pack条语句指示编译器对结构中的成员使用单字节填充。这种方式的大小Header将是 8 个字节。第二条pack语句指示返回默认设置。您可能需要使用pushpop说明(请参阅在此处输入链接描述)-但这不是您所必需的。

其次,更重要的是,您不应该使用硬编码值,例如8. 始终用于sizeof读取或写入结构。此外,绝对不需要此声明:

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

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

Header header;
...
fs.read(&header, sizeof(Header));
于 2013-03-27T06:14:48.693 回答