Почему 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);
}
Решение
ftell
не возвращает общий размер файла;он возвращает текущий читать или писать позицию внутри файла.Ты звонишь ftell
сразу после открытия файла, так что эта позиция является самым началом файла.Вы можете использовать fseek(stock, 0, SEEK_END)
искать до конца, прежде чем позвонить ftell
, или вы можете открыть слой и использовать fstat(fileno(stock))
для получения размера файла непосредственно из ОС.
Дальнейшие примечания:
- Ни один из этих вариантов не будет работать, если вы читаете из канала.(Как правило, вам необходимо проверять успешность каждой операции доступа к файлу.)
fread
не гарантирует, что он прочитает весь файл залпом, даже если вы об этом попросите.- Как отмечает «алк»,
ftell
возвращаетlong
, а неint
. - Вам следует открыть этот явно двоичный файл с режимом
"r+b"
. - Двоичные файлы без заголовка файла (и, в частности, без магическое число, по крайней мере, из четырех байтов, с нулевым смещением) являются Плохой вещью.
- Не приводите возвращаемое значение
malloc
.(Это необходимо сделать в C++, но в C это не только не нужно, это может скрыть ошибки.)
Другие советы
Проверьте справочную страницу на наличие ftell
, например этот: http://linux.die.net/man/3/ftell
Вот соответствующая часть: «Функция ftell() получает текущее значение индикатора позиции файла для потока, на который указывает поток».
Когда вы откроете файл, позиция курсора будет в начале.Таким образом, расстояние от старта будет равно нулю.Поэтому ftell
возвращает ноль.
Чтобы узнать размер файла, перейдите по этой ссылке: Как я могу получить размер файла в C?.Вот вкратце фрагмент:
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
Обязательно позвоните fseek(fp, 0L, SEEK_SET);
после вышеизложенного.
Because ftell
returns the size from the beginning to the current position of the file.
fseek(stock,0,SEEK_SET);
Means you set the position to the first bite of the file.
Also you gotta set fl_size=ftell(stock);
after the fseek
.