fread Только первые 5 байтов файла .PNG.

Я сделал простой упаковщик ресурсов для упаковки ресурсов моей игры в один файл. Все шло хорошо, пока я не начал писать распаковщик. Я заметил, что файл .txt - 26 байт - который я упаковал, вышел из файла ресурсов нормально, без каких-либо проблем, все данные сохранились. Однако при чтении файла .PNG, который я упаковал в файле ресурсов, первые 5 байтов были целы, а остальные полностью аннулированы.

Я проследил это до процесса упаковки и заметил, что fread читает только первые 5 байт файла .PNG, и я не могу понять, почему. Он даже запускает «EOF», указывая, что файл имеет длину всего 5 байтов, тогда как на самом деле это PNG размером 787 байт для небольшого многоугольника, 100 на 100 пикселей.

Я даже протестировал эту проблему, создав отдельное приложение для простого чтения этот файл PNG в буфер, я получаю те же результаты, и читаются только 5 байтов.

Вот код этого небольшого отдельного приложения:

#include <cstdio>

int main(int argc, char** argv)
{
    char buffer[1024] = { 0 };
    FILE* f = fopen("test.png", "r");
    fread(buffer, 1, sizeof(buffer), f);
    fclose(f);        //<- I use a breakpoint here to verify the buffer contents
    return 0;
}

Может кто-нибудь указать на мою глупую ошибку?

9
задан Daniel Trebbien 22 August 2010 в 22:54
поделиться

2 ответа

Кто-нибудь может указать на мою глупую ошибку?

Платформа Windows, я полагаю?

Используйте это:

FILE* f = fopen("test.png", "rb");

вместо этого:

FILE* f = fopen("test.png", "r");

См. msdn для объяснения.

21
ответ дан 4 December 2019 в 07:33
поделиться

Расширение правильный ответ от SigTerm, вот некоторые предыстории почему вы получили эффект, который вы сделали для открытия файла PNG в текстовом режиме:

Формат PNG объясняет его 8- байтовый заголовок файла следующим образом:

Первые восемь байтов файла PNG всегда содержат следующие значения:

   (decimal)              137  80  78  71  13  10  26  10
   (hexadecimal)           89  50  4e  47  0d  0a  1a  0a
   (ASCII C notation)    \211   P   N   G  \r  \n \032 \n

Эта сигнатура идентифицирует файл как файл PNG и обеспечивает немедленное обнаружение распространенных проблем с передачей файлов. . Первые два байта различают файлы PNG в системах, которые ожидают, что первые два байта однозначно идентифицируют тип файла. Первый байт выбирается как значение, отличное от ASCII, чтобы уменьшить вероятность того, что текстовый файл может быть ошибочно распознан как файл PNG; Кроме того, он обнаруживает плохие передачи файлов, которые очищают бит 7. Байты со второго по четвертый называют формат. Последовательность CR-LF отлавливает плохие передачи файлов, которые изменяют последовательность новой строки.Символ Control-Z останавливает отображение файла в MS-DOS. Последний перевод строки проверяет обратную задачу перевода CR-LF.

Я полагаю, что в текстовом режиме вызов fread() завершался при чтении шестого байта, содержащего символ Ctrl+Z. Сочетание клавиш Ctrl+Z исторически использовалось в MSDOS (а до этого в CPM) для обозначения конца файла, что было необходимо, поскольку файловая система хранила размер файла как количество блоков, а не количество байтов.

Прочитав файл в текстовом режиме вместо двоичного, вы включили защиту от случайного использования команды TYPE для отображения файла PNG.

Одна вещь, которую вы могли бы сделать, чтобы помочь диагностировать эту ошибку, — это использовать fread() немного по-другому. Вы не тестировали возвращаемое значение из fread(). Вам следует. Кроме того, вы должны называть его следующим образом:

...
size_t nread;
...
nread = fread(buffer, sizeof(buffer), 1, f);

, так что nread — это количество байтов, фактически записанных в буфер. Для файла PNG в текстовом режиме он сказал бы вам при первом чтении, что он читает только 5 байтов. Поскольку файл не может быть таким маленьким, вы бы поняли, что происходит что-то еще. Оставшиеся байты буфера никогда не изменялись с помощью fread(), что было бы видно, если бы вы инициализировали буфер другим значением заполнения.

8
ответ дан 4 December 2019 в 07:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: