Существуют ли какие-либо альтернативы stat (который есть в большинстве систем Unix), которые могут определить тип файла? В справочной странице говорится, что вызов stat стоит дорого, и мне нужно довольно часто вызывать его в своем приложении.
Альтернативы использованию stat() для получения типа файла?
Ответы (5)
Альтернативой является fstat()
, если у вас уже открыт файл (поэтому у вас есть файловый дескриптор для него). Или lstat()
, если вы хотите узнать о символических ссылках, а не о файле, на который указывает символическая ссылка.
Я думаю, что справочная страница преувеличивает стоимость; это не намного хуже, чем любой другой системный вызов, который должен преобразовать имя файла в индексный дескриптор. Это дороже, чем getpid()
; это дешевле, чем open()
.
«Тип файла», который дает вам stat()
, указывает, является ли файл обычным файлом или чем-то вроде файла или каталога устройства, среди прочего, таких как его размер и номер инода. Если это то, что вам нужно знать, то вы должны использовать stat()
.
Если вам действительно нужно знать тип содержимого файла, например. текстовый файл, изображение в формате JPEG, звук в формате MP3 — тогда у вас есть два варианта. Вы можете догадаться по расширению имени файла (если оно заканчивается на ".mp3", файл, вероятно, содержит звук в формате MP3), или вы можете использовать libmagic, которая на самом деле открывает файл и считывает часть его содержимого, чтобы выяснить, что это такое. Подход libmagic более затратный (если вы пытаетесь избежать stat()
, вы, вероятно, также захотите избежать open()
), но менее подвержен ошибкам (например, в случае, если файл ".mp3" на самом деле является изображением JPEG).
В Linux с некоторыми файловыми системами тип файла (обычный, символьное устройство, блочное устройство, каталог, канал, символическая ссылка, ...) хранится в структуре linux_dirent, в которой ядро предоставляет записи каталога приложений через системный вызов getdents. . Если единственное, что вам нужно в структуре статистики, это тип файла, и вам нужно получить его для всех или многих записей каталога, вы можете использовать getdents напрямую (а не readdir) и попытаться получить тип файла из этого, используйте stat только в том случае, если вы обнаружили недопустимый тип файла в linux_dirent. В зависимости от шаблона использования файловой системы вашего приложения это может быть быстрее, чем использование stat, если вы используете Linux, но во многих случаях stat должен быть быстрым.
Скорость Stat в основном связана с поиском запрашиваемых данных на диске. Если вы просматриваете каталог, рекурсивно отображая все файлы, то каждая статистика должна в конечном итоге быть довольно быстрой в целом, потому что большая часть работы по получению данных, необходимых для статистики, заканчивается кэшированием до того, как вы запросите это у ядра с помощью предыдущего вызова stat . С другой стороны, если вы регистрируете такое же количество файлов, случайно распределенных по системе, тогда ядру, скорее всего, придется считывать с диска несколько каталогов для каждого файла, для которого вы собираетесь вызывать stat.
fstat всегда должен быть очень быстрым, так как ядро уже должно иметь данные, которые вы запрашиваете, в ОЗУ, так как ему необходимо получить к ним доступ, чтобы файл был в открытом состоянии, и ядру не придется сталкиваться с проблемой. прохождения пути имени файла, чтобы увидеть, находится ли каждый компонент в ОЗУ или на диске и, возможно, читает в каталоге с диска (но, вероятно, не обязательно), только чтобы обнаружить, что у него есть данные, которые вы запрашиваете в ОЗУ.
При этом вызов stat для открытого файла должен быть быстрее, чем вызов для неоткрытого файла.
Знаете ли вы о «волшебном» файле в системах *nix? Запросив файл из командной строки с чем-то вроде file myfile.ext
, вы можете получить реальный тип файла.
Это делается путем чтения содержимого файла, а не просмотра его расширения, и широко используется в системах *nix (Linux, Unix, ...).
stat()
дорого, то можете себе представить стоимость запуска программы для определения типа файла?
- person Jonathan Leffler; 01.04.2010
Если предполагается, что ваше приложение будет работать в системах Linux, почему бы вам не попробовать inotify(7). Это определенно быстрее, чем stat
ing много файлов.
lstat()
, чтобы найти их. - person Jonathan Leffler   schedule 01.04.2010