在C中未遇到文件结尾(eof)
我正在尝试运行代码。除最后一张图像外,所有图像均符合规范要求 重复的前四个字节(B)如下所示:在C中未遇到文件结尾(eof),c,eof,cs50,C,Eof,Cs50,我正在尝试运行代码。除最后一张图像外,所有图像均符合规范要求 重复的前四个字节(B)如下所示: b8 97 98 c5 没有遇到文件结尾,因此发现最后一个图像已损坏 编辑: 已经提到文件中有50个图像 您可以从以下位置获取原始文件: 原代码如下: // Recovers lost images (.jpeg) in a memory card #include <stdio.h> #include <stdlib.h> #define buffsize 10 //
b8 97 98 c5
没有遇到文件结尾,因此发现最后一个图像已损坏
编辑:
// 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;
}
}
}
//恢复存储卡中丢失的图像(.jpeg)
#包括
#包括
#定义大小10
//用于检查是否为jpeg格式的函数
int check_jpeg(无符号字符*argv){
无符号int v1=(int)argv[0];
无符号整数v2=(整数)argv[1];
无符号int v3=(int)argv[2];
无符号int v4=(int)argv[3];
如果(v1==0xff&&v2==0xd8&&v3==0xff){
交换机(v4){
案例0xe0:
案例0xe1:
案例0xe2:
案例0xe3:
案例0xe4:
案例0xe5:
案例0xe6:
案例0xe7:
案例0xe9:
案例0xea:
案例0xeb:
案例0xec:
案例0xed:
案例0xee:
案例0xef:
返回1;
打破
违约:
返回0;
}
}否则{
返回0;
}
}
int main(int argc,char*argv[]){
//警告用户错误使用
如果(argc!=2){
fprintf(stderr,“用法:./recover file\n”);
返回1;
}
//打开.raw文件以开始检查
文件*camera=fopen(argv[1],“r”);
//检查打开的文件的有效性
如果(摄像机==NULL){
fprintf(stderr,“打开文件时出错:%s\n”,argv[1]);
返回2;
}
int counter=0;//声明并初始化计数器
int online=0;//了解是否正在写入映像
char*filename=(char*)malloc(buffsize);
文件*outptr;
而(1){
无符号字符*image=malloc(512);
if(image==NULL){
fprintf(stderr,“创建指针时出错\n”);
返回200;
}
fread(图像,512,1,摄像机);
如果(图像!=NULL){
int flag=检查jpeg(图像);
如果(计数器==50){
printf(“%x%x%x%x\n”,图像[0],图像[1],图像[2],图像[3]);
}
如果(标志==1){
如果(计数器!=0){
fclose(outptr);
}
计数器++;
//创建输出文件指针
snprintf(文件名,buffsize-1,“%03i.jpg”,计数器);
outptr=fopen(文件名,“w”);
if(outptr==NULL){
fprintf(stderr,“打开文件时出错:%s\n”,文件名);
返回201;
}
//写入文件
fwrite(图像,512,1,outptr);
在线=1;
}否则
如果(标志==0&&online==1){
fwrite(image,512,1,outptr);//继续写入输出文件
}
免费(图像);
}否则{
fclose(摄像机);
fclose(outptr);
返回0;
}
}
}
在读取失败时不会将指针(或至少不保证)设置为NULL。事实上,我认为应该保持指针不变<但是,code>fread将返回读取的字节数,因此您可以更改:
fread(image, 512, 1, camera);
if (image != NULL)
到
您的代码中存在多个问题:
- 您不检查有多少数据
成功读取。在文件末尾,fread
返回fread
,否则0
返回成功读入目标数组的块数。要跟踪读取的字节,请将fread
作为块大小传递,将1
作为块数传递512
- 实际上不需要分配文件名和输入/输出缓冲区,本地数组可以满足您的需要
- 文件应以二进制模式打开:
FILE*camera=fopen(argv[1],“rb”)代码>
的第二个参数应该是缓冲区大小,而不是要写入的最大字符数:snprintf
snprintf(文件名,buffsize,“%03i.jpg”,计数器)代码>
while (!feof(camera)) {
但是,这仅在读取文件时没有其他错误的情况下有效,即使这样,也始终会导致额外读取一次文件(触发EOF条件的读取)。最后一次读取可能返回坏数据或指向陈旧数据,因此需要按照@chqrlie的答案和进行处理
底线:
检查读取的字节数,如果小于请求的字节数,则使用
ferror()
和feof()
来找出原因,以便您可以相应地作出响应。我在该代码中没有看到任何检查eof
。检查fread()
的返回值。我认为没有必要动态分配image
。它也可以是一个数组。你从不检查什么东西,也不会返回。这是非常重要的,因为两者都可能失败,特别是检查fread
返回的内容,因为它会告诉您是否已到达文件结尾。此外,我非常确定关于您的问题的时间会短得多。我甚至没有检查代码,我只是观察到raw和jpeg的格式有很大的不同。@visibleman这是一个编码任务,我猜“raw”文件应该是删除图像后的一些假设磁盘内容,您的工作是检测和恢复这些内容。-无论如何,对于a,您需要创建一个简单的示例程序,其中只包含所讨论的问题(因此图像在这里是无关的)。应该交换fread
的参数:int-bytesread=fread(图像,1512,照相机)
@Pritthijit Nath,我后来才看到它,但是的,您建议的编辑也会起作用。不,这是incor
while (!feof(camera)) {