Как узнать, является ли файл каталогом (оптимальный способ)

#c #winapi

#c #winapi

Вопрос:

Я работаю в независимом от операционной системы файловом менеджере, и у меня возникла проблема с правильным определением, является ли файл каталогом или нет в Windows. dirent Структура в Windows, похоже, не имеет DT_DIR поля, поэтому я использую:

 file_attributes=GetFileAttributes(ep->d_name);
if(file_attributes amp; FILE_ATTRIBUTE_DIRECTORY)files_list[i].is_dir=1;
else files_list[i].is_dir=0;
 

Однако это не всегда точно, поскольку некоторые файлы помечены как каталоги (например, pagefile.sys ). Кроме того, GetFileAttributes это довольно медленно, если у вас много файлов.

У меня также есть функция:

 int does_dir_exist(char *path)
{
DIR *dp_test;

dp_test = opendir(path);
if(dp_test)
    {
        return 1;
        closedir(dp_test);
    }

return 0;
  }
 

Но это довольно медленно (не рекомендуется делать это для 10000 файлов).

Конечно, я могу объединить оба, что было бы довольно быстро, но есть ли лучший способ?

PS По какой-то причине не удается правильно отформатировать код для второй функции.

Комментарии:

1. Что заставляет вас говорить, что GetFileAttributes это медленно. Я далеко не уверен, что вы можете найти что-нибудь быстрее.

2. Мне трудно поверить, что некоторые файлы (такие как pagefile.sys ) имеет FILE_ATTRIBUTE_DIRECTORY включенный флаг. Возможно, в GetFileAttributes конечном итоге вы получите код ошибки -1, в котором установлены все биты

3. Я прокомментировал это, и без него это намного быстрее. И в Linux это быстрее (поскольку мне не нужно этого делать). Если у вас в каталоге около 2 тысяч файлов, и вы не обращались GetFileAttributes к ним в последнее время, это может занять несколько секунд.

4. Валдо, спасибо, это было так! Пожалуйста, укажите это в качестве ответа.

5. Да, это, конечно, правда, что a nop довольно быстро вычисляется, но это не значит, что все программы могут работать так же быстро, как nop .

Ответ №1:

Просто используйте GetFileAttributes() . opendir и closedir не собираются быстрее (вы его профилировали? Вы повторяли свои тесты, чтобы избежать эффектов кэша?).

Да, GetFileAttributes() точно. Причина, по которой вы думаете, что он терпит неудачу, заключается в том, что когда вы пытаетесь получить атрибуты pagefile.sys , он терпит неудачу и возвращается INVALID_FILE_ATTRIBUTES , что и есть (DWORD)-1 . Когда вы проверяете это с FILE_ATTRIBUTE_DIRECTORY помощью, он возвращает true , потому -1 что в нем установлен каждый бит.

На скольких файлах вы запускаете это? Какую бы функцию вы ни использовали, это будет операция, связанная с вводом-выводом, поскольку для определения атрибутов файла родительский каталог должен быть прочитан с диска (или из дискового кэша).

Комментарии:

1. Да, это было так, спасибо. Я не использую opendir / closedir для этой цели, это просто для определения где-то еще в коде, существует ли каталог или нет (и он мультиплатформенный). Метод, который я использую, — это opendir / readdir для чтения файлов, поскольку он имеет несколько шаблонов.

Ответ №2:

 _wfinddata_t fd;
_wfindfirst
_wfindnext
_findclose
 

Если вы используете эти методы для определения элементов в папке, вы получаете результат GetFileAttributes бесплатно.

Комментарии:

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