0

可能重复:
如何在 c 中读取二进制文件?(视频、图像或文本)

我正在尝试使用 C 程序读取bmp 文件的内容。我能够阅读内容,但读取的值与我的预期相矛盾。我的代码是:


FILE *fp=NULL;
fp=fopen("C:\\Users\\Saurabh\\Pictures\\nice.bmp","r");

if(fp!=NULL)
{
    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));

    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));
}

else
    printf("Error reading the file");

我只是在这里逐字节阅读,只是为了理解。读取的前两个字节BM是正确的。接下来的四个字节读取*t。预期值为 40。请参阅格式40有人可以解释一下正在发生的事情,如果我需要执行一些转换,我该如何获得价值。

4

2 回答 2

2

我相信你的问题是你如何打开文件:

fp=fopen("C:\\Users\\Saurabh\\Pictures\\nice.bmp","r"); 

“r”用于 ASCII 读取,您想以二进制打开它:

fp=fopen("C:\\Users\\Saurabh\\Pictures\\nice.bmp","rb"); 

编辑: fgetc()返回一个 int,所以我尝试使用一个 int 来获取返回值,您还想以十六进制查看结果,所以让我们使用十六进制输出格式:

FILE *readf;
int i;
unsigned int size = 0;

//Open file
readf = fopen("blackbuck.bmp", "rb");

i = fgetc(readf);
printf("%#x\n",i);   // 0x42
i = fgetc(readf);
printf("%#x\n",i);   // 0x4D
for(i=0; i<3; i++)
    size |= fgetc(readf) << (i*8); // 0xC0036

此更新将前两个值作为 0x42 0x4D,然后连接接下来的 3 个字节,给出位图的大小(0xC0036 = 786486 字节)

我使用这张图片进行测试: http: //people.sc.fsu.edu/~jburkardt/data/bmp/blackbuck.bmp

您可以看到结果具有 bmp 标头的正确字节码0x42 0x4d the header field used to identify the BMP & DIB file is 0x42 0x4D in hexadecimal, same as BM in ASCII

于 2012-09-25T15:59:48.800 回答
1

虽然我同意 Mike 的观点,即您应该以二进制模式阅读此文件,但它不应该给您带来问题。它最终会,但前 6 个字符不应中断,除非任何大小的字节包含 10 或 13。

为了读取 int,您可以执行类似的操作

int result;
fread(fp, sizeof (int), 1, &result);

但请注意,这不是便携式的。(它至少假定 32 位整数和本机字节顺序。BMP,由于它们的起源,是小端的......如果你只是在一个大的地方一次读完它,大小会很古怪 -字节序机。)

另一种方式:

unsigned long result = 0;
for (int i = 0; i < 4; ++i) {
     result |= (unsigned long) fgetc(fp) << (i * 8);
}

这至少应该总是读取正确的字节数并考虑字节序。并且unsigned long足够长以容纳任何 32 位数字,而int(即使是无符号的)也不能保证是。

于 2012-09-25T16:19:40.020 回答