использование stat для определения наличия файла (медленно?)

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

//... do something

struct stat buf;

while(stat("myfile.txt", &buf))
  sleep(1);

//... do something else

в качестве альтернативы, есть ли лучший способ проверить, существует ли файл?

3 ответов


системный вызов " stat "собирает различную информацию о файле, например, ряд жестких ссылок, указывающих на него или его номер" inode". Возможно, вы захотите взглянуть на системный вызов "access", который вы можете использовать для проверки существования, только указав флаг" F_OK "в"mode".

есть небольшая проблема с вашим кодом. Он помещает процесс в спящий режим на секунду каждый раз, когда он проверяет файл, который еще не существует. Чтобы избежать этого, вы должны использовать inotify API, как предложил Джерри гроб, для того, чтобы получить уведомление от ядра, когда файл, который вы ждете, есть. Имейте в виду, что inotify не уведомляет вас, если файл уже есть, поэтому на самом деле вам нужно использовать как "доступ", так и "inotify", чтобы избежать состояния гонки, когда вы начали наблюдать за файлом сразу после его создания.

нет лучшего или более быстрого способа проверить, существует ли файл. Если ваш файловый браузер по-прежнему показывает файл немного быстрее, чем это программа распознает его, а затем идея Грег Hewgill о переименование является, вероятно, происходит.

вот пример кода C++, который устанавливает часы inotify, проверяет, существует ли файл уже и ждет его в противном случае:

#include <cstdio>
#include <cstring>
#include <string>

#include <unistd.h>
#include <sys/inotify.h>

int
main ()
{
    const std::string directory = "/tmp";
    const std::string filename = "test.txt";
    const std::string fullpath = directory + "/" + filename;

    int fd = inotify_init ();
    int watch = inotify_add_watch (fd, directory.c_str (),
                                   IN_MODIFY | IN_CREATE | IN_MOVED_TO);

    if (access (fullpath.c_str (), F_OK) == 0)
    {
        printf ("File %s exists.\n", fullpath.c_str ());
        return 0;
    }

    char buf [1024 * (sizeof (inotify_event) + 16)];
    ssize_t length;

    bool isCreated = false;

    while (!isCreated)
    {
        length = read (fd, buf, sizeof (buf));
        if (length < 0)
            break;
        inotify_event *event;
        for (size_t i = 0; i < static_cast<size_t> (length);
             i += sizeof (inotify_event) + event->len)
        {
            event = reinterpret_cast<inotify_event *> (&buf[i]);
            if (event->len > 0 && filename == event->name)
            {
                printf ("The file %s was created.\n", event->name);
                isCreated = true;
                break;
            }
        }
    }

    inotify_rm_watch (fd, watch);
    close (fd);
}

используя inotify, вы можете организовать для ядра, чтобы уведомить вас, когда изменения в файловой системе (например, создание файла) происходит. Это вполне может быть то, что ваш браузер файлов использует, чтобы узнать о файле так быстро.


ваш код будет проверять, есть ли файл каждую секунду. вы можете использовать inotify на мероприятие.