C语言中如何按序号递增打开并写入新生成的JPEG文件?
内存卡JPEG恢复代码的问题修正
代码中的核心错误及修正方案
变量类型错误
const BLOCK_SIZE缺少int类型声明,需改为const int BLOCK_SIZE = 512;- buffer数组应使用
unsigned char类型(磁盘读取的字节为无符号数据,用int会引发符号扩展问题),改为unsigned char buffer[BLOCK_SIZE];
文件操作语法错误
fopen(card.raw, "r")中card.raw是字符串常量,必须加双引号,修正为fopen("card.raw", "r")sprintf误用文件指针pFile作为输出目标,需定义字符数组存储文件名:char filename[10];,再通过sprintf(filename, "%.03i.jpg", file_num++);生成格式正确的文件名fopen(###.jpg, "w")是无效语法,应传入生成好的filename变量,改为fopen(filename, "w")
逻辑优化(避免重复打开文件)
- 维护一个全局/局部的当前JPEG文件指针
current_img,仅在检测到新JPEG开头时关闭旧文件、打开新文件 - 循环中持续向当前打开的文件写入数据,直到下一个JPEG起始块出现
- 维护一个全局/局部的当前JPEG文件指针
修正后的完整代码
#include <stdio.h> #include <stdlib.h> const int BLOCK_SIZE = 512; unsigned char buffer[BLOCK_SIZE]; unsigned int file_num = 0; int main() { // 打开内存卡文件,增加错误检查 FILE *card_file = fopen("card.raw", "r"); if (card_file == NULL) { printf("无法打开card.raw文件\n"); return 1; } FILE *current_img = NULL; char filename[10]; // 循环读取每个512字节块 while (fread(buffer, 1, BLOCK_SIZE, card_file) == BLOCK_SIZE) { // 检测JPEG文件起始标记:前4字节为0xff 0xd8 0xff,第4字节高4位为0xe if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { // 关闭之前打开的JPEG文件(如果存在) if (current_img != NULL) { fclose(current_img); } // 生成格式为000.jpg~050.jpg的文件名 sprintf(filename, "%.03i.jpg", file_num++); // 打开新的JPEG文件准备写入 current_img = fopen(filename, "w"); if (current_img == NULL) { printf("无法创建文件%s\n", filename); fclose(card_file); return 1; } } // 如果当前有打开的JPEG文件,写入当前块数据 if (current_img != NULL) { fwrite(buffer, 1, BLOCK_SIZE, current_img); } } // 程序结束前关闭所有打开的文件 if (current_img != NULL) { fclose(current_img); } fclose(card_file); return 0; }
关键说明
- 使用
unsigned char存储buffer,确保磁盘字节数据无失真读取 - 通过
current_img指针复用文件句柄,避免重复打开/关闭文件的开销 - 增加文件打开失败的错误处理,提升程序稳定性
- 严格遵循JPEG文件的起始标记规则检测新文件,确保恢复的图片完整性
内容的提问来源于stack exchange,提问作者LifeLong21
相关产品推荐
相关产品推荐

