2013-03-19 2 views
-1

Я пытаюсь скопировать 50 jpegs, один за другим из большого файла .raw, однако в настоящее время я получаю ошибку ошибки сегментации. Вот мой код:Копирование содержимого из одного файла в другой, ошибка сегментации

#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, мой код получает весь путь, если (блок [0] == 0xFF & & блока 1 == 0xD8), то он пропускает состояние и сегментацию происходит ошибка. Я не понимаю, что может быть причиной этого. Вот скриншот: enter image description here

Код обновление:

#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; 
} 

Теперь не откажет, но только 9 из 50 JPEGs правильно восстановлены. cs50.h есть только так, что у меня есть доступ к типу bool. Каков лучший способ записать 50 файлов? У меня, похоже, есть логический недостаток с моими логическими выражениями.

+0

Я не думаю, что 'FOPEN()' 'поддерживает rd' режим – timrau

+1

' Еореп ((символ *) я, "ш +"); 'ВТФ? – nneonneo

+0

Вы не инициализировали 'jpeg_file'. –

ответ

1

fopen((char*)i, "w+"); полностью недействителен. Вы бросаете целое число как указатель, который будет сбой.

необходимо отформатировать число как имя файла:

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

Вы также не инициализируется jpeg_file - если условие не выполнено, jpeg_file будет дикий указатель, который также выходит из строя. Вы должны инициализировать jpeg_file по номеру NULL.

+0

Спасибо, я не был уверен, как это сделать. Тем не менее, все-таки срыв. – haosmark

+0

С вашим кодом много чего ... – nneonneo

+0

Можете ли вы быть более конкретным? jpeg_file был создан, но я не могу его инициализировать сразу с места в карьер, потому что мне нужно знать, какой контент писать.Я смог исправить ошибку, однако только 9 из 50 файлов правильно восстановлены. Я обновляю свой пост с помощью текущего кода, я был бы признателен, если бы вы показали мне альтернативные/лучшие способы выполнения этой задачи. Благодарю. – haosmark

0

В своем fread вызовах вы должны передать адрес массива. Следовательно, утверждение должно быть fread(block, sizeof(BYTE), 512, card_file).

Постскриптум:

  1. В вашем коде, есть предположение, что размер входного файла является целым кратным 512, который не нужен случай для JPEG файлов. Последние fread могут возвращать число меньше 512, которое должно быть обработано в вашей логике реализации. Следовательно, количество элементов для записи должно определяться возвращаемым значением fread

  2. После завершения цикла вам необходимо закрыть указатель jpeg_file.

  3. Последний, потому что вы работаете с JPEG, вы можете обрабатывать случай для EXIF ​​ файлы с иконками. В этом случае вы получите 2 SOI (начало изображения) маркеров.

+0

Это проблема из класса. Основываясь на инструкциях, я думаю, файл находится в формате FAT, и все jpegs начинаются с начала блоков памяти. Закрытие jpeg_file - это то, что я добавил, спасибо, но в этом случае это не имело значения, файлы автоматически закрыты, по крайней мере, это то, что я читаю. Что вы подразумеваете под пунктом 3? Можете ли вы привести пример, пожалуйста? ------ Я все еще сбой, после внесения всех изменений. Я также заметил, что мои первые два гексабайта равны 0, я читаю их неправильно? Я добавил printf («% X% X \ n», блок [0], блок [1]); для проверки значений – haosmark

+0

@ user1937588 Вы изменили инструкцию 'fread', чтобы удалить' '' '' '' block'? Вы наблюдаете катастрофу даже после этого изменения? Пункт 3 связан с ** EXIF ​​** файлом, в котором вы будете иметь уменьшенное изображение, встроенное вместе с основным изображением. Пожалуйста, проигнорируйте этот комментарий, если вы не знакомы с обработкой ** JPEG **. Не могли бы вы также поделиться ссылкой на автоматическое закрытие файлов, пожалуйста? – Ganesh

+0

1) Что касается файлов, то это упоминается в книге «Программирование в С», второе издание, в главе, посвященной I/O. Автор заявил, что файлы автоматически закрываются ОС, как только ваша программа будет запущена, однако он побудил читателей вручную закрыть их в любом случае. 2) Я исправил код, он работает так, как мне нужно, без сбоев, и он извлекает все jpeg. Я просто задавался вопросом о альтернативном коде/более эффективном решении. – haosmark

Смежные вопросы