Будет ли errno == ENOENT достаточной проверкой, чтобы проверить, существует ли файл в C? - PullRequest
0 голосов
/ 05 сентября 2018

Использование PellesC в Windows 8.1.

Я знаю, что эта тема была рассмотрена много раз со многими решениями. Я прочитал решения, в которых говорится об использовании CreateFile, PathFileExists, GetFileAttributes, _access, которые я несколько понимаю.

Я также прочитал важный пункт об условиях гонки в ответе на вопросы Самый быстрый способ проверить, существует ли файл и Какой лучший способ проверить, существует ли файл в C? (кроссплатформенный) .

Так что, если я открою файл, используя fopen() в C, и когда он потерпит неудачу (по любой причине) и передаст NULL назад; затем я могу дополнительно проверить errno == ENOENT, довольствоваться им и правильно сообщить, что файл не существует.

#include <stdio.h>
#include <string.h>
#include <errno.h>

int file_exists(char filename[]) {
    int err = 0; //copy of errno at specific instance
    int r = 0;   //1 for exists and 0 for not exists
    FILE *f = NULL;

    //validate
    if (filename == NULL) {
        puts("Error: bad filename.");
        return 0;
    }

    printf("Checking if file %s exists...\n", filename);

    //check
    errno = 0;
    f = fopen(filename, "r");
    err = errno;
    if (f == NULL) {
        switch (errno) {
          case ENOENT:
            r = 0;
            break;
          default:
            r = 1;
        }
        printf("errno = %d\n%s\n", err, strerror(err));
    } else {
        fclose(f);
        r = 1;
    }

    if (r == 0) {
        puts("It does not.");
    } else {
        puts("It does.");
    }

    return r;
}

1 Ответ

0 голосов
/ 05 сентября 2018

fopen нужно много чего сделать и проверить перед открытием файла. ENOENT означает , что файл не существует, но файл не существует не означает ENOENT.

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


С другой стороны, ENOENT из fopen не означает, что какой-то другой процесс не мог создать файл даже до того, как fopen вернется, или до того, как вы проверите errno и т. Д .; По этой причине C11 добавил флаг x для открытия файла для записи в монопольном режиме - сбой, если файл уже существует.


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

  • файл существовал или
  • это не может существовать
  • или он мог существовать в то время

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...