используя stat, чтобы определить, существует ли файл (медленно?) - PullRequest
6 голосов
/ 29 июля 2010

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

//... do something

struct stat buf;

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

//... do something else

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

Ответы [ 3 ]

4 голосов
/ 29 июля 2010

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

3 голосов
/ 29 июля 2010

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

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

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

Вот пример кода на 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);
}
1 голос
/ 29 июля 2010

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

...