编程作业中JPG照片恢复代码生成不完整文件问题求助
问题分析与修复方案
首先,你的代码核心问题是只在检测到JPG文件头时写入一个数据块,之后就立刻关闭输出文件,完全没有处理该JPG后续的512字节数据块——这就是为什么生成的照片都是不完整的。我们来一步步拆解问题并修复:
核心逻辑错误解析
一个完整的JPG文件由多个连续的512字节块组成,直到下一个JPG头出现(或者文件结束)。你当前的逻辑只处理了每个JPG的第一个块,后续属于该JPG的块都被忽略了,自然生成的文件都是残缺的。
具体修改点与修复后的代码
1. 调整文件读写逻辑
- 当检测到新JPG头时,先关闭之前打开的输出文件(如果有的话),再创建新文件并保持打开状态
- 未检测到新头但已有打开的输出文件时,直接将当前块写入该文件(因为这属于当前JPG的内容)
- 将文件打开模式从
"a"改为"w",避免同名旧文件的内容干扰新文件
2. 资源泄漏修复
- 记得
free之前malloc分配的filename内存 - 程序结束前检查并关闭最后一个可能仍打开的输出文件
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> typedef uint8_t BYTE; int main(int argc, char *argv[]) { if(argc != 2) { printf("Usage: ./recover IMAGE\n"); return 1; } FILE* memorycard = fopen(argv[1], "r"); if(memorycard == NULL) { printf("Could not open %s.", argv[1]); return 1; } FILE* out = NULL; int img_counter = 0; BYTE img[512]; char* filename = malloc(9 * sizeof(char)); // 足够存储"000.jpg" + 字符串终止符 while (fread(img, 512, 1, memorycard) == 1) { // 检测JPG文件头特征 if(img[0] == 0xFF && img[1] == 0xD8 && img[2] == 0xFF && (img[3] & 0xF0) == 0xE0) { // 关闭之前打开的输出文件(如果存在) if(out != NULL) { fclose(out); } // 生成新文件名并创建文件 sprintf(filename, "%03i.jpg", img_counter++); out = fopen(filename, "w"); if(out == NULL) { printf("Could not create %s.", filename); fclose(memorycard); free(filename); return 1; } // 写入当前JPG的第一个块 fwrite(img, 512, 1, out); } else { // 如果已有打开的文件,说明当前块属于该JPG,直接写入 if(out != NULL) { fwrite(img, 512, 1, out); } } } // 清理所有打开的文件与分配的内存 if(out != NULL) { fclose(out); } fclose(memorycard); free(filename); return 0; }
额外优化说明
- 把
typedef uint8_t BYTE;移到main函数外,更符合C语言的编码习惯 - 增加了
fopen失败的检查逻辑,避免空指针操作导致程序崩溃 - 确保所有文件资源和动态分配的内存都被正确释放,避免资源泄漏
内容的提问来源于stack exchange,提问作者ali nasser
相关产品推荐
相关产品推荐

