errno == ENOENT这样的检查足以判断文件在C语言中是否存在吗?
errno == ENOENT这样的检查足以判断文件在C语言中是否存在吗?
在Windows 8.1上使用PellesC编译器。
我知道这个问题已经被多次提及并有很多解决方案。我阅读了使用CreateFile
、PathFileExists
、GetFileAttributes
、_access
等方法的解决方案,我对此有一些了解。
我还在Quickest way to check whether or not file exists和What'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; }
在C语言中,我们经常使用fopen
函数来打开文件。在文件打开之前,fopen
需要进行各种检查。当文件不存在时,fopen
会返回ENOENT
错误码,表示文件不存在。然而,文件不存在并不一定意味着返回的错误码就一定是ENOENT
。
实际上,文件未找到可能会返回其他错误码,比如EACCES
表示无法读取父目录。在fopen
返回ENOENT
之前或在检查errno
之前,其他进程可能已经创建了该文件。这也是为什么C11标准在打开文件时添加了x
标志,用于以独占模式打开文件并在文件已存在时返回错误。
总结一下:如果返回ENOENT
错误码,说明在尝试打开文件时文件并不存在。如果返回其他错误码,那么这些错误码可以分为以下三类:
- 文件一定存在
- 文件一定不可能存在
- 文件可能在打开时存在
你可以根据自己的逻辑来处理这些其他错误。一个简单的处理方式是拒绝继续处理,并向用户报告错误。