Чтение шестнадцатеричного значения из изображения в C

Я пытаюсь прочитать шестнадцатеричные значения из файла изображения с помощью C. В Linux этот код работает нормально, но в Windows он читает только первые 334 байта, и я не понимаю, почему.

Код для чтения файла:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>    
void readHexFile(char* path) {
        FILE *fp;

        if ((fp = fopen (path, "r")) != NULL) {
            struct stat st;
            stat(path, &st);                

            int i;
            int ch;
            for (i = 0; i < st.st_size; i++) {
                ch = fgetc(fp);             
                printf("%x ", ch);
            }

            fclose(fp);
        }
        else {
            return NULL;
        }
}

st.st_size происходит из пакета <sys/stat.h> и содержит правильное значение (размер в байтах файла изображения)

Это изображение показывает, что выводит моя программа, и фактическое двоичное содержимое файла, который она читает:

введите здесь описание изображения Как вы видите, после последовательности 17, 18, 19 есть также шестнадцатеричные значения, но моя программа многократно печатает ffffffff.


person Davide    schedule 26.01.2017    source источник
comment
Там не видно. См. Как спросить и предоставьте минимальный воспроизводимый пример. И не публикуйте изображения текста!   -  person too honest for this site    schedule 26.01.2017
comment
Да, но изображение показывает правильные шестнадцатеричные значения   -  person Davide    schedule 26.01.2017
comment
st.st_size comes from package -- какой пакет?   -  person Wolf    schedule 26.01.2017
comment
#include ‹sys/stat.h›   -  person Davide    schedule 26.01.2017
comment
fgets, вероятно, возвращает EOF. Вероятно, вы читаете неправильную длину или используете неправильный файл.   -  person LPs    schedule 26.01.2017
comment
точный! Если я использую while... EOF, он читает до значения 0x19   -  person Davide    schedule 26.01.2017
comment
покажите нам больше вашего кода: как вы открываете файл? Непонятно, почему вы не зацикливаетесь до чего-то feof(fp)   -  person Wolf    schedule 26.01.2017
comment
Вероятно, вам также следует убедиться, что вы fopen() используете файл в двоичном режиме. Это существенная разница для unix/windows. Он всегда бинарный в unix и linux.   -  person infixed    schedule 26.01.2017


Ответы (3)


Вы открыли файл в текстовом режиме, а не как двоичный. Различные платформы могут вести себя по-разному.

В этом случае Microsoft Windows решила, что этот простой текстовый файл заканчивается при первом появлении Ctrl+Z (0x1A) и возвращает EOF для всех fgetc впоследствии.

Явно укажите, что вы хотите открыть файл как двоичный:

fp = fopen ("yourfile", "rb");

и проблема уходит.

person Jongware    schedule 26.01.2017
comment
Отлично, но если 0x1A означает Ctrl+Z, почему вы заключаете его в скобки? - person Wolf; 26.01.2017

Я думаю, что ваш цикл должен выглядеть так:

int ch;
while (!feof(fp)) {
    ch = fgetc(fp);
    printf("%x ", ch);
}

Мне совершенно непонятно, почему вы используете здесь st.st_size.

person Wolf    schedule 26.01.2017
comment
Если я использую цикл while, он печатает до 0x19, но файл становится все длиннее и длиннее. - person Davide; 26.01.2017
comment
Ну, ваша проблема, очевидно, заключалась в использовании текстового режима. Но в чем причина не использования foef: производительности? - person Wolf; 26.01.2017
comment
Да. Я использовал st.st_size, чтобы показать вам шестнадцатеричные ошибки. Да, теперь я уже использую EOF - person Davide; 26.01.2017

В Windows символ 0x1A (Ctrl+Z) является символом EOF для текстового режима; см. этот вопрос.

Если вы читаете из двоичного файла, такого как JPEG, вы должны сделать это, сначала открыв файл как двоичный (fopen режим "rb"), а затем fread в заранее выделенный буфер, размер которого вы бы определили с помощью ftell с помощью указатель файла в конце файла:

size_t i, len;
char *buffer = NULL;
fp = fopen(argv[1], "rb");
if(!fp)
   // handle error

fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);

buffer = malloc(len + 1);
if(!buffer)
    // handle error

fread(buffer, 1, len, fp);
for(i = 0; i < len; i++)
{
    printf("%.2X ", buffer[i]);
}

free(buffer);
buffer = NULL;
person Govind Parmar    schedule 26.01.2017