2015-08-02 2 views
0

Я работаю над восстановлением psc4 cs50x в Гарварде, и я застреваю, потому что open продолжает возвращать NULL.Почему open возвращает null в этом цикле? C

// Read each 512 bytes until end of file is reached 
FILE* img = NULL; 

while (fread(&data, 512, 1, diskptr) == 1) 
{ 
    // Check for jpeg start 
    if (checkStart(data, jStart, jStartOE) == true) 
    { 
     jFound++; 
     if (jFound == 1) 
     { 
      printf("newfound\n"); 
      // Name and open the first jpeg file 
      char title[12]; 
      sprintf(title, "%03d.jpg", jFound - 1); 
      FILE* img = fopen(title, "w"); 
      fwrite(&data, 512, 1, img); 
     } 
     else if (img != NULL) 
     { 
      printf("closed\n"); 
      // Close old file 
      fclose(img); 

      // Open new file 
      char title[12]; 
      sprintf(title, "%03d.jpg", jFound - 1); 
      FILE* img = fopen(title, "w"); 
      fwrite(&data, 512, 1, img); 
     } 
    } 
    else if (jFound > 0 && img != NULL) 
    { 
     printf("written\n"); 
     fwrite(&data, 512, 1, img); 
    } 
} 

Я добавил эту printfs, чтобы увидеть, если те еще, если блоки никогда не выполняется, и когда я запускаю его обретенные отпечатками один раз, а затем ничего больше отпечатков. По какой-то причине open возвращает NULL, а остальные блоки кода никогда не выполняются.

Для какого-то контекста: Цель этой программы - восстановить удаленные jpegs из .raw-файла. checkStart - это просто простая функция, которую я создал, которая определяет, содержат ли первые четыре байта блока с 512 байтами значения подписи jpeg. Если они это делают, он возвращает истинную сигнализацию о том, что текущий блок является началом нового jpeg, а если он не возвращает false. jFound - это просто переменная, которую я использовал для отслеживания того, сколько jpegs обнаружено программой, чтобы она могла правильно их назвать и записать, если первый jpeg уже найден.

+1

Проверить 'errno' после' fopen' не удалось - лучше всего предположить: слишком много открытых файлов из-за ошибки в другом месте кода. –

+0

относительно этой строки: if (checkStart (data, jStart, jStartOE) == true) 'Значение' true 'может быть различным, в зависимости от компилятора и/или содержимого файла stdbool.h. Кроме того, нет необходимости действительно проверять наличие «истины». Вот два примера инструкции, которые должны всегда работать: «if (checkStart (data, jStart, jStartOE))» <- предпочтительнее и «if (checkStart (data, jStart, jStartOE)! = false) ' – user3629249

+1

Как сказал @PaulR, 'errno' скажет вам, почему' fopen() 'не удалось. Возможно, вам будет удобнее использовать 'perror()', чем смотреть на необработанное значение 'errno'.Моя собственная первая догадка о характере ошибки будет заключаться в том, что open не работает, потому что рабочий каталог программы не доступен для записи в процессе. –

ответ

8

эта линия:

FILE* img = fopen(title, "w"); 

объявляет переменную «IMG» внутри рамки кодового блока началось с

if(iFound == 1) and if(img != NULL) 

Переменная «IMG» отличается в пределах каждого кодового блока.

Эти объявления маскируют декларацию в верхней части опубликованного кода.

Предлагайте

img = fopen(title, "w"); 

(так не объявить новую переменную 'IMG')

Эта проблема возникает в двух местах в размещенном коде.

Я также добавил некоторые ошибки проверки призывы FOPEN()

Я также удалил сверток в логике

однако, код не всегда будет поймать конец фактического файла .jpg Когда любые другие файлы также находятся в одной и той же области диска.

И если какой-либо из сегментов файла был перезаписан, код не поймает этот факт.

I.E. код может не правильно извлечь файл .jpg и записать извлеченные копии файлов может привести к перезаписи части (-ов) удаленных файлов, которые вы хотите извлечь. И.Е. поместите новые файлы на другой диск

FILE* img = NULL; 

while (fread(&data, 512, 1, diskptr) == 1) 
{ 
    // Check for jpeg start 
    if (checkStart(data, jStart, jStartOE)) 
    { 

     if (img != NULL) 
     { 
      printf("closed\n"); 
      // Close old file 
      fclose(img); 
     } 

     // Open new file 
     char title[12]; 
     sprintf(title, "%03d.jpg", jFound - 1); 

     if(NULL == (img = fopen(title, "w"))) 
     { // then fopen failed 
      perror("fopen for output file failed"); 
      exit(EXIT_FAILURE); 
     } 

     // implied else, fopen successful 

     fwrite(&data, 512, 1, img); 
    } 

    else if (img != NULL) 
    { 
     printf("written\n"); 
     fwrite(&data, 512, 1, img); 
    } 
} 
+0

, чтобы иметь любую надежду на правильную работу, 1) нужно прочитать сегменты необработанных дисков, которые fopen/fread не будут делать. 2) Для файловых систем DOS необходимо прочитать записи исходного каталога, записать символ «видимый» для первой буквы имени файла. 3) для современных файловых систем, необходимо прочитать inodes каталогов и следовать всем указателям – user3629249

+0

Спасибо! Теперь он отлично работает. Я не понимал, что объявляю новую переменную «img» внутри оператора if. Я удалил FILE * и успешно восстановил все изображения. – epiqueras

+0

Примечание для справок в будущем: всегда компиляция с включенными предупреждениями - компилятор предупредил бы вас об этих затененных ошибках переменных. –