ftell / fseek отличается от общей длины данных в файле - PullRequest
0 голосов
/ 24 апреля 2019

встроенная система Linux

  1. ls -al / sys / class / xxxx

    -r - r - r-- 4096

  2. ftell / lstat (st_size) return 4096

  3. fread (fp, 1, 4096, buf) return 3

На самом деле в файле всего 3 байта, использующих vi для его открытия.

В чем проблема? Спасибо.

Ответы [ 3 ]

1 голос
/ 24 апреля 2019

/sys - это специальная файловая система, в которой файлы генерируются ядром по требованию. Подробнее см. man sysfs(5):

Файловая система sysfs является псевдофайловой системой, которая предоставляет интерфейс для структур данных ядра. (Точнее, файлы и каталоги в sysfs предоставляют представление о структурах kobject, определенных внутри ядра.) Файлы в sysfs предоставляют информацию об устройствах, модулях ядра, файловых системах и других компонентах ядра.

Размер файлов в /sys, сообщаемый ls, не является фактическим размером, поскольку содержимое файлов генерируется не только для получения размера файла. Содержимое генерируется только после системного вызова read.

Также обратите внимание, что fseek и ftell также не сообщат о фактическом размере файла для sysfs, потому что, опять же, содержимое файла генерируется только в read syscall.

0 голосов
/ 24 апреля 2019

В чем проблема?

Проблема в том, что fseek() / ftell() - принципиально несостоятельный способ получить размер файла.

Файлы могут быть открыты в двоичном или текстовом режиме.

Для бинарных файлов fseek(file, 0, SEEK_END) - это явно неопределенное поведение. В соответствии с сноской 268 стандарта C :

Установка индикатора положения файла в конец файла, как и в fseek(file, 0, SEEK_END), имеет неопределенное поведение для двоичного потока (из-за возможных завершающих нулевых символов) или для любого потока с кодированием, зависящим от состояния, которое не гарантированно заканчивается в начальном состоянии смены.

За 7.21.9.2 Функция fseek , параграф 3 :

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

Так что не существует переносимого, совместимого со стандартами способа поиска конца двоичного потока.

И вы не можете использовать ftell(), чтобы получить размер файла, открытого в текстовом режиме. Для 7.21.9.4 Функция ftell , пункт 2 (обратите внимание на выделенные части):

Функция ftell получает текущее значение индикатора положения файла для потока, на который указывает stream. Для двоичного потока значение представляет собой количество символов в начале файла. Для текстового потока его индикатор положения файла содержит неопределенную информацию , используемую функцией fseek для возврата индикатора положения файла для потока на его позицию во время вызова ftell; разница между двумя такими возвращаемыми значениями не обязательно является значимым показателем количества написанных или прочитанных символов.

Вы не можете искать конец двоичного потока, и вы не можете использовать ftell, чтобы получить размер текстового потока.

0 голосов
/ 24 апреля 2019

В системе Unix размер блока файловой системы должен составлять 4 КБ.
Я не хочу повторного ответа, поэтому проверьте это:

https://unix.stackexchange.com/questions/62049/why-are-text-files-4kb
https://en.wikipedia.org/wiki/File_system#Space_management

Если вы хотите иметь реальный размер файла в байтах, используйте это:

fp = fopen("...", "rb");
fseek(fp, 0L, SEEK_END);
size_t size = ftell(fp);

И если вы хотите прочитать из файла сброса, начните поиск:

rewind(fp);

OR

fseek(fp, 0L, SEEK_SET);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...