检查文件是否存在的C语言方法

14
在我要使用C89标准完成的一个项目中,我需要检查文件是否存在。我该怎么做?
我考虑使用:
FILE *file;
if ((file = fopen(fname, "r")) == NULL)
{
  printf("file doesn't exists");
}
return 0;

但我认为有更多的情况会导致fopen == NULL,而不仅仅是文件不存在。

我该如何做到这一点?我更喜欢使用“.”而不是包含。


1
如果fopen()失败(即返回0),则您不必(也不能!)关闭文件句柄。只有在成功时才需要这样做。 - Mario
1
我认为在C89标准中没有更好的方法。如果允许POSIX或其他标准,请参见https://dev59.com/lHVC5IYBdhLWcg3woStW。 - interjay
5个回答

14
如果在你的环境中无法使用stat()函数(这绝对是更好的方法),只需评估errno变量即可。不要忘记包含errno.h头文件。
FILE *file;
if ((file = fopen(fname, "r")) == NULL) {
  if (errno == ENOENT) {
    printf("File doesn't exist");
  } else {
    // Check for other errors too, like EACCES and EISDIR
    printf("Some other error occured");
  }
} else {
  fclose(file);
}
return 0;

编辑:忘记把fclose放在else里了

(注:该段内容与IT技术无关)

“-1 for ENOENT”是一个错误代码,但它并不是C89标准的一部分,正如OP所要求的那样。它的实现是定义的,并不能保证存在。C89标准规定:“实现还可以指定以E和数字或E和大写字母开头的其他宏定义。” - Wiz
你是对的,这不是标准中的内容(我想这是有好的原因的)。如果代码应该在所有C89实现中都可以完全移植,那么这不是正确的方法。另一方面,支持ENOENT是广泛可用的,所以使用上述方法通常不是一个坏主意,除非你的平台是非常特殊的(嵌入式系统等)。你也可以简单地放弃如果fopen返回-1并忽略具体的错误,就像问题中给出的例子一样。 - onitake
+1 表示 ENOENT。它是 POSIX 标准中的一部分,使用它比使用 stat 更好,因为后者可能会导致竞态条件和安全问题。 - Fred Foo
2
为什么使用stat()比使用带有F_OKaccess()更好? - einpoklum

3

在纯ISO标准C中,无法检查某些的存在性。 确定命名文件是否存在没有真正好的便携式方法;您可能需要使用特定于系统的方法。


2
这不是一个可移植的东西,所以我将为您提供特定于操作系统的调用。
在Windows中,您使用 GetFileAttributes 并检查返回值是否为-1( INVALID_HANDLE 或类似内容)。
在Linux中,您可以使用 fstat 来实现此目的。
然而,大多数情况下,我只是使用文件打开技巧进行测试,或者直接使用文件并检查异常(C++ / C#)。

2

您真的想访问该文件吗?通常使用<unistd.h>中的access(filename,F_OK)==0进行检查,这是一个相当广泛的标准。


1

我猜这更多与系统环境(如POSIX或BSD)有关,而不是你使用的C语言版本。

在POSIX中,有一个stat()系统调用可以提供有关文件的信息,即使您无法读取它。但是,如果文件位于您没有访问权限的路径中,则无论文件是否存在,它始终会失败。

如果您无法访问该路径,则永远不应该有可能查看包含的文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接