在C中未遇到文件尾(eof)

时间:2018-08-02 09:59:17

标签: c eof cs50

我正在尝试运行代码。除最后一张图像外,所有图像均符合规格要求。

重复的前四个字节(B)如下:

b8 97 98 c5

未遇到文件末尾,因为发现最后一张图像已损坏。

编辑:

  1. 已经提到文件中有50张图像。
  2. 您可以从以下位置获取原始文件:http://cdn.cs50.net/2017/fall/psets/4/recover/card.raw

原始代码如下:

// Recovers lost images (.jpeg) in a memory card

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

#define buffsize 10

// Function to check whether jpeg or not
int check_jpeg(unsigned char *argv) {
    unsigned int v1 = (int)argv[0];
    unsigned int v2 = (int)argv[1];
    unsigned int v3 = (int)argv[2];
    unsigned int v4 = (int)argv[3];
    if (v1 == 0xff && v2 == 0xd8 && v3 == 0xff) {
        switch (v4) {
          case 0xe0:
          case 0xe1:
          case 0xe2:
          case 0xe3:
          case 0xe4:
          case 0xe5:
          case 0xe6:
          case 0xe7:
          case 0xe9:
          case 0xea:
          case 0xeb:
          case 0xec:
          case 0xed:
          case 0xee:
          case 0xef:
            return 1;
            break;
          default:
            return 0;
        }
    } else {
        return 0;
    }
}

int main(int argc, char *argv[]) {
    // Cautioning the user for wrong usage
    if (argc != 2) {
        fprintf(stderr, "Usage: ./recover file\n");
        return 1;
    }

    // Opens the .raw file to begin inspection
    FILE *camera = fopen(argv[1], "r");

    // Checks the validity of the opened file
    if (camera == NULL) {
        fprintf(stderr, "Error opening file: %s\n",argv[1]);
        return 2;
    }

    int counter = 0; // Declaring and Initialising the counter
    int online = 0; // To know whether image is being written

    char *filename = (char*)malloc(buffsize);
    FILE *outptr;

    while (1) {
        unsigned char *image = malloc(512);
        if (image == NULL) {
            fprintf(stderr, "Error creating pointer \n");
            return 200;
        }
        fread(image, 512, 1, camera);
        if (image != NULL) {
            int flag = check_jpeg(image);
            if (counter == 50) {
                printf("%x %x %x %x\n", image[0], image[1], image[2], image[3]);
            }
            if (flag == 1) {
                if (counter != 0) {
                    fclose(outptr);
                }
                counter++;

                // Creating the output file pointer
                snprintf(filename, buffsize - 1, "%03i.jpg", counter);
                outptr = fopen(filename, "w");
                if (outptr == NULL) {
                    fprintf(stderr, "Error opening file: %s\n", filename);
                    return 201;
                }

                // Writing to the file
                fwrite(image, 512, 1, outptr);
                online = 1;
            } else
            if (flag == 0 && online == 1) {
                fwrite(image, 512, 1, outptr); // Continue writing to the output file
            }
            free(image);
        } else {
            fclose(camera);
            fclose(outptr);
            return 0;
        }
    }
}

3 个答案:

答案 0 :(得分:2)

您的代码中存在多个问题:

  • 您不检查fread成功读取了多少数据。在文件末尾,fread返回0,否则fread返回成功读入目标数组的块数。要跟踪字节读取情况,请将1作为块大小,将512作为 blocks 的数目。
  • 实际上没有必要分配文件名和输入/输出缓冲区,本地数组可以满足您的需求。
  • 文件应以二进制模式打开:FILE *camera = fopen(argv[1], "rb");
  • snprintf的第二个参数应该是缓冲区大小,而不是要写入的最大字符数:snprintf(filename, buffsize, "%03i.jpg", counter);

答案 1 :(得分:0)

fread不会在读取失败时将指针(或至少不能保证)设置为NULL。实际上,我认为应该保持指针不变。 fread将返回读取的字节数,因此您可以更改:

   fread(image, 512, 1, camera);
   if (image != NULL)

   int bytesread=fread(image, 1, 512, camera);
   if (bytesread!= 512)

答案 2 :(得分:0)

您可能会想做以下事情:

while (!feof(camera)) {

但是,这仅在没有其他错误读取文件的情况下有效,即使如此,也总是导致对文件的另一次读取(触发EOF条件的读取)。最后一次读取可能会返回错误数据或指向过期数据,因此需要按照@chqrlie的答案和this previous question about feof()进行处理。

底线: 检查读取的字节数(如果少于请求的字节数),请使用ferror()feof()找出原因,以便您做出相应的反应。