C fopen 写入失败,errno 为 2

Posted

技术标签:

【中文标题】C fopen 写入失败,errno 为 2【英文标题】:C fopen fails for write with errno is 2 【发布时间】:2013-03-23 02:19:27 【问题描述】:

我不明白为什么这似乎以 errno 为 2 失败:

char debugText [256];
sprintf (debugText, "C:\\List.txt");
dfile = fopen( debugText, "w");
fprintf ( dfile, "  err %d \n", errno);

我说的似乎是因为当 dfile 为 NULL 时,文件被创建并填充了我的输出。

那是怎么回事?

【问题讨论】:

dfile 是什么类型? NULL 的测试在哪里? 看看strerror(),它会返回一个字符串,为您解释errno (对于 googlers)对我来说,文件没有写权限。在 Windows 上:右键单击 > 属性 > 安全 > 编辑。然后允许所有用户修改 @SergioBasurco 也许这是一个更好的解决方法,使文件指向允许普通用户写入的位置。不是每个人都在他们的电脑上拥有管理员访问权限,这些权限不应用于纠正编程错误。 【参考方案1】:

这一切都告诉你,errno 在你调用fopen 之后的值为 2。你不知道调用失败,因为你没有检查是否dfile == NULL。如果输出实际上已写入文件,则可能是 fopen 调用成功,而 errno 值是先前调用留下的,可能是您没有明确调用的。

失败的调用可以将errno设置为某个非零值,但成功的调用不要errno设置为0。要检查错误,您需要

调用前将errno设置为0; 进行调用并检查它返回的值,看它是成功还是失败;和 在调用后检查errno 的值——但如果你知道它失败了(否则errno 的值没有意义)。

如果defile == NULL,则fprintf 调用具有未定义的行为;它可能会失败。

另一方面,你说dfileNULL。你怎么知道?你的代码没有检查它。 (如果fopen 调用真的失败了,C:\List.txt 的内容是否会从您的程序的先前运行中遗留下来?)

你从这个程序得到什么输出?

#include <stdio.h>
#include <errno.h>
int main(void) 
    char debugText [256];
    FILE *dfile;

    sprintf (debugText, "C:\\List.txt");
    dfile = fopen( debugText, "w");
    if (dfile == NULL) 
        printf("fopen failed, errno = %d\n", errno);
    
    else 
        printf("fopen succeeded\n");
    
    return 0;

【讨论】:

我看到 dfile 为 NULL,因为我在调试模式下单步执行。那是我开始抓取 errno 的时候。 您需要检查defile == NULL是否在您的程序中,如果是则不要尝试写入文件。要验证fopen() 失败的原因,请按照我对errno 的建议进行操作。假设您在 Windows 系统上,打开 "C:\\List.txt" 进行输出不应以 errno==2 失败,这意味着“没有这样的文件或目录”。 (您在 Windows 上,对吗?而不是在 Cygwin 下?) @JPM:试试我刚刚添加到答案中的程序。【参考方案2】:
2 ENOENT No such file or directory.  A component of a specified pathname
         did not exist, or the pathname was an empty string.

这里是错误代码列表:

http://www.thegeekstuff.com/2010/10/linux-error-codes/

但是您应该首先检查fopen() 是否返回NULL,因为errno 中的这个值可能是其他东西留下的。

【讨论】:

【参考方案3】:

没有库函数将errno 设置为零。

您应该只在函数报告错误后检查errno

例如,您的代码应该是:

if ((dfile = fopen(debugText, "w")) == 0)
    ...then fopen() failed and errno is relevant...

如果函数不报告失败,errno 中的值可能是任何值。例如,在 Solaris 上,您经常在成功操作后将errno 设置为ENOTTY,因为stdout 没有连接到终端。这并不意味着实际上出了什么问题。它只是意味着测试标准输出是否是终端失败(因为它不是终端)。

【讨论】:

如果文件确实存在 fopen 应该删除然后创建一个新文件。显然路径不是空的,路径也不是不存在的:C:\ 所以我不明白为什么 dfile 为 NULL。除非那是 VS2010 的异常? 你没有证明dfile == NULL;事实上,由于下面的fprintf() 使用它,所以dfile 不可能为空(如果它为空,您可能会在fprintf() 中崩溃)。您必须修改代码以明确测试 dfile,然后我才愿意相信您的断言 dfile 为空(并在 dfile 以外的频道上报告错误)。【参考方案4】:

在我的情况下,我在尝试打开文件以写入具有 FAT 文件系统的挂载闪存驱动器时收到了errno == 2;事实证明,如果文件不符合8.3 rule,fopen 返回NULL 并将errno 设置为ENOENT

有必要说,我在嵌入式系统上遇到过这种情况,在 Windows 上应该不是问题。

【讨论】:

是的,我的错。编辑了我的答案。

以上是关于C fopen 写入失败,errno 为 2的主要内容,如果未能解决你的问题,请参考以下文章

fwrite(): XX 字节写入失败,errno=5 输入/输出错误

如何获取 IOError 的 errno?

C语言中的fopen函数的具体实现是怎么样?

C语言读取文件

fopen()函数

fopen参数介绍