为什么 'fopen' 返回一个空指针?

22

我正在使用C语言编写一个简单的文件分离/合并程序。问题是,由于某种原因,fopen返回了NULL,并且因此,我的程序在fwrite语句处崩溃。我该如何解决这个问题?

这是C文件:

int SplitFile(char* filename, char* output, size_t size)
{
    char current_file_name[256];
    int file_count = 0, i = 0;
    FILE *file = fopen( filename, "rb" );
    printf("split %s into chunks of %d named\n", filename, size);

    if (!file)
       return E_BAD_SOURCE;
    else
    {
        output = (char *) malloc(size * sizeof(char));
        if (output == NULL)
            return E_NO_MEMORY;
        else
        {
            int bytes_read = 0;
            FILE *outFile;
            do
            {
                bytes_read = fread(output, sizeof(char), size, file );
                sprintf(current_file_name, "%s%04lu\n", "part", file_count++);
                outFile = fopen (current_file_name, "wb" );  // THIS RETURNS NULL
                fwrite(output, sizeof(char), bytes_read, outFile); //CRASHES ON THIS LINE
            }
            while ( bytes_read > 0 )
                ;

            //fclose(outFile);
        }
    }
    fclose(file);
    printf("...\n");
    return 0;
}

1
尖刻 - 在尝试写入文件之前,请检查文件是否已打开。真正的答案是您可能没有文件系统权限或者它位于不存在的文件夹路径中。 - EnabrenTane
11
errno 存储的是什么错误?只需添加 if (!outFile)perror("fopen"); ,让库告诉您它失败的原因即可。 :) - sarnold
在 errno 中,我得到了 fopen: 无效的参数。 - k787
你是否提供了正确的路径? - Shweta
请使用默认路径(包含 .c 和 .h 文件的文件夹)。我认为这与路径无关。 - k787
8个回答

22

fopen返回NULL时,正确的做法是检查errno

我猜测你的问题是尝试写入不允许在文件名中使用\n的文件系统,但也可能是权限问题。


1
更加妥当的做法是在fopen返回NULL时检查errno。你可能是想使用fopen而不是fwrite。 - Windows programmer
当我注释掉sprintf并执行以下操作时; outFile = fopen("part000", "wb"); 它可以正常工作。 - k787
@user:你把sprintf行中的\n去掉了吗? - Gabe
1
@user:文件名中不允许使用\n字符。这会导致fopen失败,因此它返回NULL。 - Gabe
1
能看到检查 errno 的示例会很有帮助。这也是我们来这里学习的原因 :) - jenkizenki
显示剩余2条评论

12

fopen 可能返回 NULL 的原因有很多,包括但不限于以下几种:

  • 文件不存在
  • 以不允许其他访问的模式打开文件
  • 网络故障
  • 文件存在,但你没有权限
  • 存在一个与所给名称相同的文件,但进程当前目录不是预期的目录,导致相对路径名无法找到并打开该文件。

要找出造成这些问题的原因,可以查看 errno 代码。

然而,仅仅因为解决了这个特定的错误,就不能假设 fopen 将永远不会返回 NULL。在处理 I/O 操作时,代码必须始终考虑失败的情况。I/O 操作的成功是无法预测的,它们总是可能失败的。


空间不足怎么办?这会导致它返回NULL吗? (我知道你说“不限于”,我的问题不是修辞手法) - Nande
@Nande: fopen() 可能会在磁盘已满的情况下成功或失败,这取决于是否需要扩展目录(且你未用尽i节点)。如果不需要扩展目录(并且没有用完i节点),则它可以成功打开文件。但是,接下来的fwrite() fclose()!)将失败。 - Davis Herring

2

这意味着文件可能不存在,或者在访问文件(如“只读”或“写保护”)时发生了某些权限错误,因此在这些情况下,fopen将返回0(一个空指针)。成功时,它将返回文件指针作为处理程序。

fp = fopen("c:\\ABC.txt", "r");不能与fp = fopen("c:\\abc.txt", "r");相同。

在Linux环境中,请使用//代替\\

P.S.:在Linux和类Unix操作系统中,文件名区分大小写。


0

文件路径是从可执行文件所在的位置进行检查的。 在我的情况下,当C文件和文本文件同时存在时,我正在打开文本文件。 它一直报错找不到文件。 将文件放置在可执行文件的文件夹中,它就开始工作了。


0
在我的情况下,是因为我试图在一个不存在的目录中创建文件。

0
在Unix中,对于fopen()函数,没有必要在传递给它的文件名前面加上"./"。

0
在我的情况下,我在 while 循环中一遍又一遍地读取同一个文件,并忘记关闭它。
我使用了一个函数来读取文件并查找匹配项,该函数有一个 return; 语句,在执行 fclose(fp) 之前终止了函数 :D

0

fopen在第一次运行时是否返回NULL?

我注意到在while循环中,您保持打开文件进行写入但没有关闭它们。

尝试在fwrite之后添加fclose(outFile):

outFile =  fopen ( current_file_name , "wb" );    
fwrite(output, sizeof( char ), bytes_read, outFile); 
fclose(outFile)

你可能打开了比操作系统允许的更多的文件。


是的,我也这么想,关闭了文件,但是没有起作用。 - k787

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