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

如何判断在C中打开输入文件是否失败 动机,c,file-io,error-handling,C,File Io,Error Handling,如果我确定给定的输入文件存在,我想循环,直到为该文件创建“文件流”没有失败 问题: 我理解,通过下面的检查,我们可以判断在C中是否打开输入失败(因此,所述文件存在于本地) #包括 #包括 int main() { FILE*rec_in_FILE=fopen(“filename.txt”,“r”); //如果无法打开文件,请报告错误并退出 if(rec_in_file==NULL) { fprintf(stderr,“无法打开输入文件!”); 出口(1); } 返回0; } 但是,如何判断文件

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

问题: 我理解,通过下面的检查,我们可以判断在C中是否打开输入失败(因此,所述文件存在于本地)

#包括
#包括
int main()
{
FILE*rec_in_FILE=fopen(“filename.txt”,“r”);
//如果无法打开文件,请报告错误并退出
if(rec_in_file==NULL)
{
fprintf(stderr,“无法打开输入文件!”);
出口(1);
}
返回0;
}

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

检查
errno
或调用
peror()
可以在
fopen()失败后获取信息。问题是,这些方法不需要生成任何与I/O错误相关的信息。实现通常会这样做,但并不要求这样做,而且信息也各不相同


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

检查
errno
或调用
peror()
可用于在
fopen()失败后获取信息。问题是,这些方法不需要生成任何与I/O错误相关的信息。实现通常会这样做,但并不要求这样做,而且信息也各不相同


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

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上运行良好。微软的
fopen
很好地将
errno
设置为2,其
strerror
字符串为
“无此类文件或目录”
。这2对应于Microsoft提供的
enoint
常量
EPERM
存在,且值为1。记录设置
errno
的行为;以下引用直接出自MSDN:“[i]如果发生错误,将设置全局变量errno,并可用于获取特定的错误信息。”


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

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

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

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

提示:如果您使用的是较旧的C语言,或者使用的是避免混合声明和语句的风格,那么您可以使用sti
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");
}