You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:30:48