在 Windows 上的文件结束之前到达 EOF

问题描述

#include <stdio.h>
#include <stdlib.h>

const int size = 512;
int main(int argc,char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr,"Usage: ./recover image\n");
        return 1;
    }

    FILE *file = fopen(argv[1],"r");
    if (file == NULL)
    {
        fprintf(stderr,"Could not open file\n");
        return 1;
    }
    unsigned char buffer[size];
    int count = 0;
    FILE *jpeg = NULL;

    while(fread(buffer,size,1,file))
    {
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            char image[7];
            if (count != 0)
            {
                fclose(jpeg);
            }
            sprintf(image,"%03i.jpg",count);
            jpeg = fopen(image,"w");
            if (jpeg == NULL)
            {
                fprintf(stderr,"Couldn't open file\n");
                return 1;
            }
            count++;
        }
        if (count != 0)
        {
            fwrite(&buffer,jpeg);
        }
    }
    fclose(file);

}

代码在 card.raw 中查找 jpeg 当我在 linux 上运行上面的代码时,它运行正常。但在 Windows 上,代码只读取 card.raw 文件的前三个 512 字节块。 我做错了什么? 我也在 linux 上使用 clang。在 Windows 上我使用的是 gcc。

解决方法

首先,二进制文件应该以二进制模式打开。这意味着您应该将 "rb""wb" 用于 fopen() 模式,而不是 "r""w"。否则,换行符可能会被不必要地转换,它们可能会在字节 0x1a 处停止。

其次,对数组 sprintf(image,"%03i.jpg",count); 执行 char image[7]; 是不好的。 sprintf() 的结果将是(至少)7 个字符,因此需要具有 8 个或更多元素的数组来存储包括终止空字符的字符串。为了安全起见,您应该使用 snprintf(),它接受​​缓冲区大小。