如果我确定给定的输入文件存在,我想循环,直到创建文件的“文件流”没有失败。
据我所知,通过以下检查,我们可以判断在C中打开输入是否失败(因此,所述文件存在于本地),
vagrant plugin install nokogiri --plugin-version 1.6.7.1
但是如何判断文件是否存在但是在创建“文件流”时出现了问题?在对这个问题的初步研究中,我没有提到处理这个案子的提及。
答案 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
,并且将无效参数处理程序配置为允许继续执行。