errno == ENOENT这样的检查足以判断文件在C语言中是否存在吗?

8 浏览
0 Comments

errno == ENOENT这样的检查足以判断文件在C语言中是否存在吗?

在Windows 8.1上使用PellesC编译器。

我知道这个问题已经被多次提及并有很多解决方案。我阅读了使用CreateFilePathFileExistsGetFileAttributes_access等方法的解决方案,我对此有一些了解。

我还在Quickest way to check whether or not file existsWhat's the best way to check if a file exists in C? (cross platform)的答案中读到了有关竞争条件的重要观点。

所以,如果我在C中使用fopen()打开一个文件,当它失败(无论出于什么原因)并返回NULL时,我可以进一步检查errno == ENOENT并正确报告文件不存在吗?

#include 
#include 
#include 
int file_exists(char filename[]) {
    int err = 0; //errno在特定位置的副本
    int r = 0;   //1表示存在,0表示不存在
    FILE *f = NULL;
    //验证
    if (filename == NULL) {
        puts("错误:文件名错误。");
        return 0;
    }
    printf("检查文件 %s 是否存在...\n", filename);
    //检查
    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("不存在。");
    } else {
        puts("存在。");
    }
    return r;
}

0
0 Comments

在C语言中,我们经常使用fopen函数来打开文件。在文件打开之前,fopen需要进行各种检查。当文件不存在时,fopen会返回ENOENT错误码,表示文件不存在。然而,文件不存在并不一定意味着返回的错误码就一定是ENOENT

实际上,文件未找到可能会返回其他错误码,比如EACCES表示无法读取父目录。在fopen返回ENOENT之前或在检查errno之前,其他进程可能已经创建了该文件。这也是为什么C11标准在打开文件时添加了x标志,用于以独占模式打开文件并在文件已存在时返回错误。

总结一下:如果返回ENOENT错误码,说明在尝试打开文件时文件并不存在。如果返回其他错误码,那么这些错误码可以分为以下三类:

  • 文件一定存在
  • 文件一定不可能存在
  • 文件可能在打开时存在

你可以根据自己的逻辑来处理这些其他错误。一个简单的处理方式是拒绝继续处理,并向用户报告错误。

0