Чтение бинарного и текстового файлов — по 1 байту за раз

Я пытаюсь написать код, который читает 1 байт (идеальная цель - n байтов, но начиная с 1 байта - поэтому для n байтов, если это проще, предложите)

Ниже приведен код, который я пытался прочитать по 1 байту за раз и вывести его в шестнадцатеричном формате. Но все это куча FFFF

    FILE *fp;
    int stringlength,i;

    /* File can be txt or .bin */
    fp = fopen("TestFile3.txt", "r");
    if (fp == NULL) 
    {
        puts("Error: Input file cannot be read");
        return -1;
    }
    else 
    {
        size_t i, strlength, lengthOfFile,c;
        fseek(fp, 0, SEEK_END);
        lengthOfFile = ftell(fp);
        printf("length of File is ---- %d \n", lengthOfFile);
        while (lengthOfFile)
        {
            c = fgetc(fp);
            printf("%c", c);
            lengthOfFile--;
        }
        putchar('\n');

    }
    fclose(fp);
    return 0; 
}

person oneday    schedule 18.08.2015    source источник
comment
fseek(fp, 0, SEEK_END); - Как вы думаете, что это делает?   -  person Iłya Bursov    schedule 19.08.2015
comment
вы искали до конца файла, затем продолжайте читать, что означает, что вы ничего не читаете, кроме EOF....   -  person Marc B    schedule 19.08.2015
comment
Перейдя в конец файла, вы получите EOF только тогда, когда прочитаете больше данных, не так ли?   -  person Jonathan Leffler    schedule 19.08.2015
comment
Просто из соображений стиля вам не нужен else при выходе из предыдущего блока кода.   -  person Weather Vane    schedule 19.08.2015
comment
Спасибо всем за указатель - да, я понимаю ошибку   -  person oneday    schedule 19.08.2015
comment
Чтобы прочитать n байт, взгляните на fread   -  person Kninnug    schedule 19.08.2015
comment
Вы не показали c, но если это int c, то все можно сделать с помощью while ((c = fgetc(fp)) != EOF) {...}   -  person Weather Vane    schedule 19.08.2015
comment
c должно быть int, size_t — очень неправильный тип. И прочитайте о синтаксисе строки формата и правильных аргументах.   -  person too honest for this site    schedule 19.08.2015
comment
@Olaf - Спасибо - буду иметь в виду.   -  person oneday    schedule 19.08.2015


Ответы (2)


Вам нужно fseek(fp, 0, SEEK_SET); для сброса указателя файла перед циклом while.

person artm    schedule 18.08.2015

Вы также открываете файл в «текстовом» режиме:

fp = fopen("TestFile3.txt", "r");

Согласно стандарту C, раздел 7.19.2 :

Текстовый поток — это упорядоченная последовательность символов, состоящая из строк, каждая строка состоит из нуля или более символов плюс завершающий символ новой строки. Требует ли последняя строка завершающего символа новой строки, зависит от реализации. Символы могут быть добавлены, изменены или удалены при вводе и выводе, чтобы соответствовать различным соглашениям для представления текста в хост-среде. Таким образом, не обязательно должно быть однозначное соответствие между символами в потоке и во внешнем представлении.

Использование fseek()/ftell() не возвращает количество байтов, доступных для чтения из текстового потока.

Вам нужно открыть файл в двоичном режиме, если вы хотите прочитать каждый байт в соответствии с размером файла:

fp = fopen("TestFile3.txt", "rb");

Наконец, использование fseek()/ftell() также ненадежно для двоичных файлов, потому что, опять же, в соответствии со стандартом C, 7.19.9.2:

Двоичный поток не обязательно должен поддерживать вызовы fseek со значением where, равным SEEK_END.

Учитывая это, вы также не можете надежно использовать fseek()/ftell(), чтобы узнать, насколько велик двоичный файл. И да, примеры есть.

Чтобы надежно прочитать все байты в файле, @Weather Vane опубликовал в комментариях один из способов сделать это.

person Andrew Henle    schedule 19.08.2015