C语言恢复存储卡删除JPEG失败:生成图片无法加载求调试方案
JPEG文件恢复代码问题排查与调试技巧
问题描述
我编写了一段C语言代码用于恢复存储卡中已删除的JPEG文件,代码可编译运行,但生成的输出图片始终无法加载。需要排查代码中的问题,同时获取针对这类仅在输出后才显现问题的代码的调试技巧。
问题代码
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <stdint.h> const int BLOCKSIZE = 512; FILE *img = NULL; int main(int argc, char *argv[]) { //Check if there is only 1 argument entered if (argc != 2) { printf("Usage: ./recover ###.jpg\n"); return 1; } //open memorry card and ensure that it's readable FILE *raw_memory = fopen(argv[1], "r"); if (raw_memory == NULL) { printf("Could not open file\n"); return 2; } //Repeat until the end of card: uint8_t *buffer = malloc(BLOCKSIZE); int jpg_counter = 0; bool jpg_found = false; while (true) //Read 512 bytes into a buffer { size_t bytes_read = fread (buffer, 1, BLOCKSIZE, raw_memory); // If end of raw_memory reached, exit loop if (bytes_read < BLOCKSIZE) { break; } // If start of new JPG if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { //Open new raw_memory and start writing //If first JPG raw_memory if (jpg_counter == 0) { //Open new raw_memory and start writing char str[100]; sprintf(str, "%03i.jpg", jpg_counter); img = fopen(str, "w"); if (img == NULL) { printf("Could not open jpeg file\n"); return 3; } fwrite(buffer, sizeof(buffer), 1, img); jpg_counter++; jpg_found = true; } else //close previously file and open a new one { fclose(img); jpg_found = false; char str[100]; sprintf(str, "%03i.jpg", jpg_counter); img = fopen(str, "w"); if (img == NULL) { printf("Could not open jpeg file\n"); return 4; } fwrite(buffer, sizeof(buffer), 1, img); jpg_found = true; jpg_counter++; } } else { if (jpg_found) { fwrite(buffer, sizeof(buffer), 1, img); } } } fclose(img); fclose(raw_memory); free(buffer); }
代码问题排查
- 文件打开模式错误:JPEG是二进制文件,用
"w"文本模式写入会在Windows系统下转换换行符(把0x0A转为0x0D0A),破坏二进制结构,必须改用二进制模式"wb"打开输出文件。 - fwrite参数错误:
sizeof(buffer)得到的是指针的大小(4或8字节),不是你分配的512字节缓存区大小。应改为fwrite(buffer, 1, BLOCKSIZE, img),确保每次写入完整的512字节块。 - 末尾数据丢失:当读取到不足512字节的块时直接退出循环,但这部分数据如果属于当前正在写入的JPG,需要写入文件后再退出。
- 空指针风险:如果没有找到任何JPG文件,
img会保持NULL,最后执行fclose(img)会导致程序崩溃,需要在fclose前判断img != NULL。
针对这类问题的调试技巧
- 二进制文件对比:用十六进制编辑器(如HxD)对比原始存储卡镜像中的JPG数据和生成的文件,查看开头签名、数据内容是否一致,定位出错环节。
- 关键日志输出:在代码中添加printf,输出每次fread的字节数、fwrite的字节数、JPG计数器变化、文件打开/关闭状态,确认流程是否符合预期。
- 分步验证:先只恢复第一个JPG文件,确认能正常打开后再处理多文件场景,逐步缩小问题范围。
- 检查返回值:不要忽略fread、fwrite的返回值,这些值能反映实际读写的字节数,帮助判断是否出现异常。
- 临时文件校验:将每次写入的数据输出到临时文件,用图片查看工具或格式校验工具检查是否符合JPG格式要求。
内容的提问来源于stack exchange,提问作者Sizwe
相关产品推荐
相关产品推荐

