Почему ftell возвращает 0 в этой функции?

Когда я запускаю свою программу и выбираю просмотр списка продуктов, она ничего не печатает. Через какое-то время я узнаю, что значение fl_size всегда равно 0. Почему это так?

void view_prdct_code_list() {
        FILE *stock = fopen("stock.dat","r+");
        assert(stock);

        int fl_size=ftell(stock);
        int prd_size= sizeof(product);
        int quantity= fl_size/prd_size;
        printf("fl_size=%d",fl_size);

        fseek(stock,0,SEEK_SET);
        prdct cprd= (product *)malloc (sizeof(product)*quantity);
        assert(cprd);

        int i;

        fread(cprd,prd_size,quantity,stock);

        for (i=0;i<quantity;i++){
                printf("PRODUCT CODE: %d\n",cprd->code);
        }

        free(cprd);
        fclose(stock);
}

person Dot    schedule 03.06.2014    source источник
comment
OT: ftell() возвращает long, поэтому вам лучше использовать long для сохранения результата, а int.   -  person alk    schedule 03.06.2014


Ответы (3)


ftell не возвращает общий размер файла; он возвращает текущую позицию чтения или записи в файле. Вы вызываете ftell сразу после открытия файла, так что эта позиция является самым началом файла. Вы можете либо использовать fseek(stock, 0, SEEK_END) для поиска до конца перед вызовом ftell, либо вы можете раскрыть слой и использовать fstat(fileno(stock)) для получения размера файла непосредственно из ОС.

Дополнительные примечания:

  1. Ни один из этих вариантов не будет работать, если вы читаете из канала. (Вообще, вам нужно проверять успешность каждой из ваших операций доступа к файлам.)
  2. fread не гарантирует, что прочитает весь файл залпом, даже если вы попросите его об этом.
  3. Как указывает 'alk', ftell возвращает long, а не int.
  4. Если long составляет всего 32 бита, файл может быть настолько большим, что его размер не помещается в long. Если ваша программа должна обрабатывать такие большие файлы, вам нужно #define _FILE_OFFSET_BITS 64 в начале каждого файла .c (перед всеми включениями) и использовать fseeko и ftello. (Или какой-либо эквивалент Windows.)
  5. Вы должны открывать этот явно двоичный файл в режиме "r+b".
  6. Двоичные файлы без заголовка файла (и, в частности, без магического номера, по крайней мере четыре байта по нулевому смещению) — это Плохая вещь.
  7. Не приводить возвращаемое значение malloc. (Это необходимо сделать в C++, но в C это не только не нужно, но и может скрывать ошибки.)
person zwol    schedule 03.06.2014

Проверьте справочную страницу для ftell, например, эту: http://linux.die.net/man/3/ftell

Вот соответствующая часть: "Функция ftell() получает текущее значение индикатора позиции файла для потока, на который указывает stream."

Когда вы открываете файл, позиция курсора будет в начале. Таким образом, расстояние от начала будет равно нулю. Поэтому ftell возвращает ноль.

Чтобы узнать размер файла, см. эту ссылку: Как я могу получить размер файла в C?. Вот фрагмент в кратце:

fseek(fp, 0L, SEEK_END);
sz = ftell(fp);

Обязательно позвоните fseek(fp, 0L, SEEK_SET); после того, как указано выше.

person bytefire    schedule 03.06.2014
comment
С любой современной библиотекой C (и под современным я подразумеваю совместимость с C89) вы можете написать 0 вместо 0L. L был необходим только с библиотеками C, которые не предоставили прототип для fseek. - person zwol; 03.06.2014

Потому что ftell возвращает размер от начала до текущей позиции файла.

fseek(stock,0,SEEK_SET);

Означает, что вы установили позицию на первый фрагмент файла.

Также вы должны установить fl_size=ftell(stock); после fseek.

person Edenia    schedule 03.06.2014
comment
Разве fseek(stock,0,SEEK_SET); не должно быть fseek(stock,0L,SEEK_END);? то есть перейдите в конец файла, а затем подсчитайте позицию. Этот пост не кажется правильным ответом. - person bytefire; 03.06.2014
comment
Честно говоря, я просто использую fseek(stock,0,SEEK_END); при подсчете размера неподвижного изображения. Вот почему я забыл указать смещение. К тому же я просто цитирую. - person Edenia; 03.06.2014