fread into struct错误地读取数据

时间:2016-06-12 21:35:25

标签: c struct fread

我正在尝试将位图(.bmp)图像标题读入c中的struct

typedef unsigned short WORD;
typedef unsigned long DWORD;

typedef struct _BITMAPFILEHEADER {
    WORD Type;
    DWORD Size;
    WORD Reserved1;
    WORD Reserved2;
    DWORD OffBits;
} BITMAPFILEHEADER;

我的代码来读取位图文件

FILE *fp;
BITMAPFILEHEADER header;

fp = fopen(file,"rb");
if (fp == NULL) {
    printf("cannot open file!\n");
    return 1;
}

fread(&header, sizeof(BITMAPFILEHEADER), 1, fp);

printf("Type: %02x\n", header.Type);
printf("Size: %04x\n", header.Size);
printf("Reserved: %02x\n", header.Reserved1);
printf("Reserved: %02x\n", header.Reserved2);
printf("Offset: %04x\n", header.OffBits);

一切应该是平等的:
输入:0x424d
大小:0x00060436
保留1:0x00
保留2:0x00
抵消:0x00000436

实际上是多么开心(printf输出):
输入:0x424d
大小:0x0006
保留:0x002
保留:0x436
抵消:0x280000

(如果有帮助,我的操作系统是32位ubuntu)

1 个答案:

答案 0 :(得分:0)

在阅读这种文件时,我认为一种好的方法是首先将它们作为字节流(unsigned char)读取,然后,如果需要,根据适当的方式解释部分文件内容数据类型。

在您的情况下,例如,我将像这样定义BITMAPFILEHEADER结构:

typedef struct _BITMAPFILEHEADER {
    unsigned char   Type[ 2 ];
    unsigned int    Size;          // Size of the BMP file in bytes 
    unsigned char   Reserved1[ 2 ];
    unsigned char   Reserved2[ 2 ];
    unsigned int    OffBits;       // Starting address of the pixel array 
} BITMAPFILEHEADER;

然后我会将标题内容读作14个字节的块,最后,我会继续正确地填充BITMAPFILEHEADER结构。

下面你可以找到一个简单的程序,它读取BMP文件的标题并将其打印到屏幕上。

int main
    (
    )
    {
    // Defines a few variables
    FILE*           fp   =  0;
    unsigned char   h[ 14 ];

    // Opens the BMP file
    fp   =   fopen( "img.bmp", "rb" );

    if ( fp == NULL )
        {
        printf( "Cannot open file\n" );
        return -1;
        }

    // Reads the BMP header (14 bytes)
    fread( h, 14, 1, fp );

    // Prints the header contents
    printf( "Type:     %02x%02x\n", h[ 0 ], h[ 1 ] );
    printf( "Size:     %02x%02x%02x%02x\n", h[ 2 ], h[ 3 ], h[ 4 ], h[ 5 ] );
    printf( "Reserved: %02x%02x\n", h[ 6 ], h[ 7 ] );
    printf( "Reserved: %02x%02x\n", h[ 8 ], h[ 9 ] );
    printf( "Offset:   %02x%02x%02x%02x\n", h[ 10 ], h[ 11 ], h[ 12 ], h[ 13 ] );

    return 0;
    }

注1 - 填充:根据BMP文件格式规范,我们知道标头长度为14个字节,而printf( "%d", sizeof(BITMAPFILEHEADER) )将显示不同(更大!)的数字填充(请参阅您的问题的评论)。

注2 - Endiannes:当分别将2或4个字节写入短或长时,您必须考虑到endiannes。这意味着您必须知道如何将值写入文件(对于Bitmap标头,它们使用小端符号表示)以及机器如何处理它们(可能以小端符号表示)。