如何判断C中的打开输入文件是否失败

时间:2016-04-07 23:49:33

标签: c file-io error-handling

动机

如果我确定给定的输入文件存在,我想循环,直到创建文件的“文件流”没有失败。

问题

据我所知,通过以下检查,我们可以判断在C中打开输入是否失败(因此,所述文件存在于本地),

vagrant plugin install nokogiri --plugin-version 1.6.7.1

但是如何判断文件是否存在但是在创建“文件流”时出现了问题?在对这个问题的初步研究中,我没有提到处理这个案子的提及。

2 个答案:

答案 0 :(得分:3)

errno失败后,可以使用perror()fopen()的来电来获取信息。问题在于,这些方法不需要产生任何与I / O错误相关的信息。实现经常这样做,但不需要它们,信息也各不相同。

一般来说,您需要使用标准C之外的函数,例如access()stat()(大多数Unix库支持),PathFileExists()(Windows API)或其他一些函数主机系统提供的手段。

答案 1 :(得分:3)

fopen函数可能(但可能不会)设置errno以指示失败的具体原因。如果没有,那么可能无法检测到原因,或者您正在处理标准库的非常差的实现。

  

为什么fopen的实现者不会设置errno标准C错误原因报告机制,除非由于某种原因它很难或根本无法完成?如果fopen 可以确定无法打开文件的具体原因,那么将errno设置为某个值就很简单了。如果这很难以使C库实现者摆脱它,那么在这个平台上对你来说可能并不容易。

由于fopen可能未设置errno(ISO C不需要它),这会产生歧义:如果fopen失败,errno非零,我们不知道fopen是否设置了该值,或者它是否已经非零。解决方案是:在尝试fopen之前为errno分配零

提示:如果您使用较旧的C方言,或者使用避免混合声明和语句的样式,您仍然可以使用逗号表达式执行此操作:

FILE *f = (errno = 0, fopen(...));

逗号表达式的值和类型是右操作数的值。

然后,在fopen失败的情况下,测试errno是否已更改为非零。如果是这样,它可能包含与fopen有关的信息。您可以使错误消息更具信息性,或采取一些特殊操作:

if (fp == NULL) {
    if (errno != 0)
      fprintf(stderr, "Could not open input file, for this reason: %s\n!",
              strerror(errno));
    else
      fprintf(stderr, "Could not open input file, for some reason.\n");
}

提示:您可以使用#ifdef查看是否存在特定的errno常量。例如,如果您要检查并为POSIX EPERM执行一些特殊操作,请使用#ifdef EPERM ... #endif包装该代码。

请注意,上述errno方法在使用MSVCRT(Microsoft Visual C运行时)C库(无Unix仿真层)的Microsoft Windows上正常工作。 Microsoft的fopen很好地将errno设置为2,strerror字符串为"No such file or directory"。这2对应于Microsoft提供的ENOENT常量。 EPERM存在且值为1.设置errno的行为已记录在案;以下引用直接来自MSDN:“[i]发生错误,全局变量errno已设置,可用于获取特定错误信息。”

如果您传递空字符串,Microsoft的fopen也将失败并将errno设置为EINVAL,并且将无效参数处理程序配置为允许继续执行。