Иногда вы хотите проверить, существует ли файл, прежде чем выполнять некоторые манипуляции с файлами, такие как резервное копирование, копирование, изменение или просто чтение данных. Однако C/C++ не предоставляет никаких встроенных функций для проверки существования файла. К счастью, мы можем использовать другие встроенные функции для разработки собственной функции проверки существования файла. Есть несколько способов выполнить эту задачу, но какой из них самый быстрый и лучший.

функция std::ios:good()

В первом подходе мы получаем поток из файла с помощью ifstream , а затем проверяем состояние потока, хорошее оно или нет. Функция good() является частью класса ios, который является базовым классом для потоков, и фактически ifstream наследует эту функцию от класса ios. Функция возвращает true, если ни один из флагов состояния ошибки потока (eofbit, failbit и badbit) не установлен.

bool isFileExist (const std::string& name) {
        ifstream file(name.c_str());
        return file.good();
}

запустив эту функцию 10 000 раз, половину из которых использовали файлы, которые существовали, а другую половину — файлы, которые не существовали, и потребовалось:

Duration: 506975 ms

функция fopen()

При другом подходе мы попытаемся прочитать данные из файла с помощью функции fopen(), которая является частью стандартной библиотеки C. Если мы можем прочитать данные из файла, значит, файл существует, иначе нет.

bool isFileExist (const std::string& name) {
    if (FILE *file = fopen(name.c_str(), “r”)) {
       fclose(file);
       return true;
    } else {
       return false;
    } 
}

Выполнение функции с теми же 10 000 выборок, что и в предыдущем случае, приводит к следующему результату:

Duration: 469158 ms

функция access() POSIX

Библиотека C POSIX — это независимая от языка библиотека (с использованием соглашений о вызовах C), которая добавляет функции, специфичные для систем POSIX. Система POSIX — это «интерфейс переносимой операционной системы», представляющий собой семейство стандартов, которые первоначально пытались сделать все различные системы UNIX совместимыми. Таким образом, вы можете писать с использованием POSIX API, и если вы не используете не-POSIX API, у вас, вероятно, будет программа, которая будет работать в различных вариантах UNIX, а затем и в других операционных системах, поддерживающих POSIX.

access() является частью библиотеки C POSIX, она проверяет, может ли вызывающий процесс получить доступ к файлу путь. Если pathname является символической ссылкой, она разыменовывается. Режим указывает проверки доступности, которые должны быть выполнены, и является либо значением F_OK, либо маской, состоящей из побитового ИЛИ одного или нескольких из R_OK, W_OK и X_OK. F_OK проверяет существование файла.

bool isFileExist (const std::string& name) {
      return ( access( name.c_str(), F_OK ) != -1 );
}

Запуск функции с теми же тестами, что и раньше:

Duration: 388544 ms

stat() POSIX-функция

stat() — это еще одна функция posix, которая считывает атрибуты файла. Функция stat() возвращает ноль (0), если операция прошла успешно, иначе, если файл не существует, она возвращает -1.

Мы можем использовать функцию stat() для проверки существования файла следующим образом:

bool isFileExist (const std::string& name) {
     struct stat buffer;
     return (stat (name.c_str(), &buffer) == 0);
}

Что касается результатов, stat()иaccess() — это, безусловно, самый быстрый способ проверить существование файла в стандарте C/C++, если только вы не хотите используйте любую из функций posix.

Duration: 377680 ms

Вердикт

В конце концов, все зависит от того, где находятся файлы. Например, если все они должны находиться в одном каталоге, вы можете прочитать все записи каталога в хэш-таблицу, а затем проверить все имена по хеш-таблице. В некоторых системах это может работать быстрее, чем проверка каждого файла по отдельности. Самый быстрый способ проверить каждый файл по отдельности зависит от вашей системы… если вы пишете ANSI C, самый быстрый способ — fopen, потому что это единственный способ (файл может существовать, но не открываться, но вы, вероятно, действительно хотите открыть его, если вам нужно «сделать что-то с этим»). Библиотека C POSIX, предлагает дополнительные возможности и, возможно, более быструю работу в некоторых системах, которые вы можете изучить и использовать.