【问题标题】:Why does 'fopen' return a NULL pointer?为什么“fopen”返回一个 NULL 指针?
【发布时间】:2011-08-24 15:55:00
【问题描述】:

我正在使用 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;
}

【问题讨论】:

  • Snarky - 在尝试写入之前检查打开的文件。真正的答案是您可能没有文件系统权限,或者它位于不存在的文件夹路径中
  • errno 中存储了什么错误?只需添加 if (!outFile)perror("fopen"); 并让库告诉您失败的原因。 :)
  • 在 errno 中我得到 fopen : Invalid Argument
  • 你的路径是否正确?
  • 它应该使用默认路径(包含 .c 和 .h 的文件夹)。我不认为它与路径有关

标签: c null fopen fwrite


【解决方案1】:

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

我猜你的问题是你试图写入一个不允许\n在文件名中的文件系统,但这也可能是一个权限问题。

【讨论】:

  • 更正确的做法是在 fopen 返回 NULL 时检查 errno。您可能指的是 fopen 而不是 fwrite。
  • 当我注释掉 sprintf 并执行此操作时; outFile = fopen(“part000”,“wb”);它工作正常。
  • @user:那么,你有没有把\n 从你的sprintf 行中去掉?
  • @user:文件名中不允许使用\n 字符。这会导致 fopen 失败,因此它返回 NULL。
  • 查看检查errno 的示例会有所帮助。这就是我们在这里学习的原因:)
【解决方案2】:

fopen for write 在第一次运行时返回 NULL 吗?

我注意到在您保留打开的文件进行写入但没有关闭它们的同时。

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

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

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

【讨论】:

  • 是的,我也有同样的想法并关闭了文件,但没有用
【解决方案3】:

正如 Gabe 所说,您的问题是文件名中的换行符,这在 Windows 中是非法的。

但是你为什么不直接使用 GNU Core Utilities 中的 split。在 Unices/Linux 上默认安装,可从GnuWin32 project 下载 Windows。

split --suffix-length=4 --numeric-suffixes --bytes=1M - part < filename

【讨论】:

    【解决方案4】:

    fopen 可以返回NULL 的原因有很多,包括(但当然不限于):

    • 文件不存在
    • 文件以不允许其他访问的模式打开
    • 网络中断
    • 文件存在,但您没有权限
    • 存在您提供的名称的文件,但进程的当前目录不是您所期望的,因此相对路径名无法找到并打开该文件。

    找出谁负责的方法是挖掘errno代码。

    但是,仅仅因为您解决了这个特定错误并不意味着您可以假设 fopen 永远不会返回 NULL。在处理 I/O 操作时,您的代码只需要预期失败。无法预测 I/O 操作的成功,它们总是会失败。

    【讨论】:

    • 空间不足怎么办?那不会使它返回NULL吗? (我知道你说“不限于”我的问题不是修辞)
    • @Nande: fopen() 在完整磁盘上创建新文件可能会成功,也可能不会成功。如果目录不需要扩展(并且您没有用完 inode),它可以成功,但后面的 fwrite() fclose()!)将失败。
    【解决方案5】:

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

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

    在 Linux 环境中使用 // 而不是 \\

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

    【讨论】:

      【解决方案6】:

      在 Unix 中,对于 fopen(),没有理由在传递给 fopen() 的文件名前添加 ./。

      【讨论】:

        【解决方案7】:

        在我的例子中,我在一个 while 循环中重新读取同一个文件并忘记关闭它。

        我使用了一个函数来读取文件并找到匹配项,该函数有一个 return; 语句在执行 fclose(fp) 之前终止了该函数:D

        【讨论】:

          【解决方案8】:

          从存在可执行文件的任何位置检查为文件指定的路径。 就我而言,当两者都存在于同一个地方时,我正在打开 c 文件中的文本文件。 它不断给出找不到文件的错误。 将文件放在可执行文件的文件夹中,它开始工作。

          【讨论】:

            【解决方案9】:

            就我而言,这是因为我试图在不存在的目录中创建文件。

            【讨论】:

              猜你喜欢
              • 2011-10-04
              • 2022-01-02
              • 2012-01-14
              • 1970-01-01
              • 1970-01-01
              • 2011-05-24
              • 1970-01-01
              • 2013-12-27
              • 1970-01-01
              相关资源
              最近更新 更多