-1

我正在尝试从一个大的 .raw 文件中一一复制 50 个 jpeg,但是目前我遇到了分段错误错误。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef uint8_t BYTE;

//SOI - 0xFF 0xD8
//EOI - 0xFF 0xD9
//APPn - 0xFF 0xEn    
int main(void)
{
    //FAT - 512 bytes per block
    BYTE block[512];

    //open file containing pictures
    FILE* card_file = fopen("card.raw", "rd");

    FILE* jpeg_file;

    //make sure the file opened without errors
    if (card_file == NULL)
    {
        printf("something went wrong and file could not be opened");
        return 1;
    }

    int i = 0;
    while (fread(&block, sizeof(BYTE), 512, card_file) != 0)
    {
        //jpeg start signature
        if(block[0] == 0xFF && block[1] == 0xD8)
        {
            i++;
            if(jpeg_file != NULL)
                fclose(jpeg_file);

            //create a new jpeg file to copy bytes to
            jpeg_file = fopen((char*)i, "w+");
        }

        //write 512 bytes to a jpeg file
        if(jpeg_file != NULL)
            fwrite(block, sizeof(block), 1, jpeg_file);
    }

    fclose(card_file);
return 0;
}

当我通过 GDB 运行它时,我的代码一直到 if(block[0] == 0xFF && block 1 == 0xD8),然后它会跳过条件并发生分段错误。我看不出是什么原因造成的。这是一个屏幕截图: 在此处输入图像描述

代码更新:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <cs50.h>

typedef uint8_t BYTE;

/*struct jpg*/
/*{*/
/*    BYTE soi[2] = { 0xFF, 0xD8 };*/
/*    BYTE eoi[2] = { 0xFF, 0xD9 };*/
/*};*/

//SOI - 0xFF 0xD8
//EOI - 0xFF 0xD9
//APPn - 0xFF 0xEn    
int main(void)
{
    //FAT - 512 bytes per block
    BYTE block[512];

    //jpeg name
    char name[6];

    bool is_open = false;

    //JPEG
    //struct jpg image;

    //open file containing pictures
    FILE* card_file = fopen("card.raw", "r");

    FILE* jpeg_file;

    //make sure the file opened without errors
    if (card_file == NULL)
    {
        printf("something went wrong and file could not be opened");
        return 1;
    }

    int i = 0;
    while (fread(block, sizeof(BYTE), 512, card_file) != 0)
    {
        //jpeg start signature
        if ((block[0] == 0xFF) && (block[1] == 0xD8) && (block[2] == 0xFF) && ((block[3] == 0xe1) || (block[3] == 0xe0)))
        {
            //assign jpeg name
            sprintf(name, "%d.jpg", i++);
            if(is_open)
                fclose(jpeg_file);

            //create a new jpeg file to copy bytes to
            jpeg_file = fopen(name, "a+");
            is_open = true;
        }

        //write 512 bytes to a jpeg file
        if(is_open)
            fwrite(block, sizeof(block), 1, jpeg_file);
    }

    fclose(jpeg_file);
    fclose(card_file);
return 0;
}

现在它不会崩溃,但是 50 个 jpeg 中只有 9 个被正确恢复。cs50.h 在那里,所以我可以访问 bool 类型。编写 50 个文件的更好方法是什么?我的布尔值似乎存在逻辑缺陷。

4

2 回答 2

1

fopen((char*)i, "w+");完全无效。您将整数转换为指针,这将崩溃。

您需要将数字格式化为文件名:

char path[PATH_MAX];
sprintf(path, "%d", i);
fopen(path, "w+");

您也没有初始化jpeg_file——如果条件失败,jpeg_file将是一个野指针,它也会崩溃。您应该初始化jpeg_fileNULL.

于 2013-03-19T00:28:59.343 回答
0

在您的fread通话中,您应该传递数组的地址。因此,陈述应该是fread(block, sizeof(BYTE), 512, card_file)

后记:

  1. 在您的代码中,假设输入文件的大小是 512 的整数倍,而JPEG文件不需要这种情况。最后一个fread可能会返回一个小于 512 的数字,这需要在您的实现逻辑中进行处理。因此,要写入的元素数量应由fread

  2. 您需要jpeg_file在循环终止后关闭指针。

  3. 最后,因为您使用的是JPEG,您可能需要处理带有缩略图的EXIF文件的情况。在这种情况下,您将获得 2 个SOI(图像开始)标记。

于 2013-03-19T00:29:38.253 回答