在 C 中没有遇到文件结尾 (eof)
Not encountering end of file (eof) in C
我正在尝试 运行 代码。除最后一张外,所有图像都按照规格正常运行。
前四个字节(B)重复如下:
b8 97 98 c5
没有遇到文件结尾,因为发现最后一张图像已损坏。
编辑:
- 已经提到文件中有50张图片。
- 您可以从以下位置获取原始文件: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;
}
}
}
fread
不会在读取失败时将指针(或至少不保证)设置为 NULL。事实上,我认为应该保持指针不变。然而,fread
将 return 读取的字节数,因此您可以更改:
fread(image, 512, 1, camera);
if (image != NULL)
至
int bytesread=fread(image, 1, 512, camera);
if (bytesread!= 512)
您的代码中存在多个问题:
- 你没有检查
fread
成功读取了多少数据。在文件末尾,fread
returns 0
,否则 fread
returns 成功读入目标数组的块数。要跟踪读取的字节,请将 1
作为块大小传递,将 512
作为 块的数量传递 .
- 没有真正需要分配文件名和 input/output 缓冲区,本地数组可以满足您的需要。
- 文件应该以二进制模式打开:
FILE *camera = fopen(argv[1], "rb");
snprintf
的第二个参数应该是缓冲区大小,而不是要写入的最大字符数:snprintf(filename, buffsize, "%03i.jpg", counter);
您可能会想做以下事情:
while (!feof(camera)) {
但是,这仅在读取文件时没有其他错误的情况下有效,即使这样,也总是会导致对文件进行一次额外的读取(触发 EOF 条件的一次)。最后一次读取可能 return 错误或指向陈旧数据,因此需要根据@chqrlie 的回答和 this previous question about feof().
进行处理
底线:
检查读取的字节数,如果小于请求的字节数,则使用 ferror()
和 feof()
找出原因,以便您做出相应的响应。
我正在尝试 运行 代码。除最后一张外,所有图像都按照规格正常运行。
前四个字节(B)重复如下:
b8 97 98 c5
没有遇到文件结尾,因为发现最后一张图像已损坏。
编辑:
- 已经提到文件中有50张图片。
- 您可以从以下位置获取原始文件: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;
}
}
}
fread
不会在读取失败时将指针(或至少不保证)设置为 NULL。事实上,我认为应该保持指针不变。然而,fread
将 return 读取的字节数,因此您可以更改:
fread(image, 512, 1, camera);
if (image != NULL)
至
int bytesread=fread(image, 1, 512, camera);
if (bytesread!= 512)
您的代码中存在多个问题:
- 你没有检查
fread
成功读取了多少数据。在文件末尾,fread
returns0
,否则fread
returns 成功读入目标数组的块数。要跟踪读取的字节,请将1
作为块大小传递,将512
作为 块的数量传递 . - 没有真正需要分配文件名和 input/output 缓冲区,本地数组可以满足您的需要。
- 文件应该以二进制模式打开:
FILE *camera = fopen(argv[1], "rb");
snprintf
的第二个参数应该是缓冲区大小,而不是要写入的最大字符数:snprintf(filename, buffsize, "%03i.jpg", counter);
您可能会想做以下事情:
while (!feof(camera)) {
但是,这仅在读取文件时没有其他错误的情况下有效,即使这样,也总是会导致对文件进行一次额外的读取(触发 EOF 条件的一次)。最后一次读取可能 return 错误或指向陈旧数据,因此需要根据@chqrlie 的回答和 this previous question about feof().
进行处理底线:
检查读取的字节数,如果小于请求的字节数,则使用 ferror()
和 feof()
找出原因,以便您做出相应的响应。