fopen() 无法打开文件

fopen() is unable to open file

提问人:Default 提问时间:6/26/2023 最后编辑:Default 更新时间:6/26/2023 访问量:172

问:

我正在尝试打开一个文件并阅读其中的内容。但是,我目前只是试图打开它。

这是我的代码:

void read_contents(char* file_path)
{
    printf("\nOriginal path: %s\n", file_path);

    // Trying to prefix the path with "." to indicate that the path is relative.
    char prefix[1024] = ".";
    
    strcat(prefix, file_path);

    // Printing to make sure that prefix contains correct path.
    printf("\nPath after concatenating: %s\n", prefix);

    FILE* file = fopen(prefix, "r");

    if (file == NULL)
    {
       perror("Error");
    
       // Close the file and stop the function.
       fclose(file);
       return;
    }


    // Code to read the file...
    // ...
    // Code to read the file...


    fclose(file);
}

这是输出:(请记住,它甚至没有到达阅读部分)

Original path: /input_files/file_1.txt

Path after concatenating: ./input_files/file_1.txt

Error: no such file or directory

这是我的目录结构:

root:

executable
input_files (this is a folder)
  file_1.txt

可执行文件与名为“input_files”的文件夹位于同一级别。input_files内部是文本文件所在的位置。

其他事项:

  1. 我正在从终端运行正确的可执行文件。
  2. 传递给函数时路径正确。
  3. 我的文件夹和文件的结构和名称是正确的。
  4. 访问和读取文件的权限是正确的。
  5. “.”正确地添加到字符串的开头。

有了这一切,我仍然收到一个错误,说没有这样的文件或目录。谁能告诉我我错过了什么?

C 字符串 文件 fopen

评论

1赞 President James K. Polk 6/26/2023
如果您试图弄清楚为什么文件似乎找不到,请始终打印出当前工作目录作为调试工作的一部分。
1赞 user207421 6/26/2023
你为什么要在前面加点?这完全改变了路径的含义。
2赞 Allan Wind 6/26/2023
如果失败了,你不想这样做。开头的路径是绝对路径,其他一切都是相对的。路径 ./x' 与 .fopen()fclose()/x
1赞 n. m. could be an AI 6/26/2023
把你的程序放在一边。在同一终端中,键入 。你观察到什么?cat ./input_files/file_1.txt
1赞 linuxfan says Reinstate Monica 6/26/2023
根据您的设置,如果由“./executable”执行,程序应该可以工作。如果你用“../executable“,那么它将不起作用。

答:

1赞 Allan Wind 6/26/2023 #1

我无法重现该错误,这可能意味着您当前的工作目录可能与预期不同。这是您应该提供的程序,而不是将打印出当前工作目录 (cwd) 的不完整代码片段:

#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void read_contents(char* file_path) {
    printf("Original path: %s\n", file_path);
    char prefix[strlen(file_path)+2];
    strcpy(prefix, ".");
    strcat(prefix, file_path);
    printf("Path after concatenating: %s\n", prefix);
    FILE* file = fopen(prefix, "r");
    if (!file) {
        perror("Error");
        char cwd[PATH_MAX];
        getcwd(cwd, PATH_MAX);
        printf("cwd: %s\n", cwd);
        return;
    }
    fclose(file);
}

int main(void) {
    read_contents("/input_files/file_1.txt");
    read_contents("/input_files/non-existing.txt");
}

下面是一个示例运行:

Original path: /input_files/file_1.txt
Path after concatenating: ./input_files/file_1.txt
Original path: /input_files/non-existing.txt
Path after concatenating: ./input_files/non-existing.txt
Error: No such file or directory
cwd: /home/...

评论

0赞 Default 6/26/2023
不幸的是,您的解决方案不起作用。我仍然收到相同的错误,说找不到该文件。我仔细检查了文件夹结构、文件名和调试语句以及我的可执行文件的当前工作目录,它们似乎都是正确的。我不明白为什么这不起作用。
0赞 Allan Wind 6/27/2023
如果您遇到相同的错误,那么您没有使用我的程序,因为它会生成不同的输出。
0赞 Allan Wind 6/27/2023
它还应该在接受的答案中修复问题(在发布之前)。
2赞 Artyom Grigorian 6/26/2023 #2

在阅读了此类情况下所有可能和常见的解决方案后,这些解决方案在您的案例中不起作用,我唯一的猜测可能是传递给函数的格式错误的 C 字符串,乍一看可以被视为正确。 我设法在我的网站上重现了类似的问题,只是将格式错误的 C 字符串指针传递给了read_contents函数。

主要思想。假设您的 main 函数中有一些静态初始化的数组,其长度大于文件路径的长度。在我复制的案例中,我采用了包含 100 字节的字节数组。

char path2[100] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x02};

我也有

char path[] = "/file.txt" // strlen on this will result in 10 (includes \0)

将 9 个字节的内存从路径(不包括 \0)复制到 path2 缓冲区后

memcpy(path2, path, 9);

请注意,我已经为 path2 - byte 中的 null-terminator 字节准备了替换(它可以是任何垃圾值) 将内存从正确的缓冲区复制到 path2 缓冲区后。生成的字符串也是正确的,如果我们将其打印出来,我们会看到完全相同的字符串,但是null 终止符之前的最后一个字节是0x02,而不是初始路径中的最后一个符号。 准确地说,path2 缓冲区在 memcpy 之后将如下所示。0x02

2F 66 69 6C 65 2E 74 78 74 02 00 .... 00
/  f  i  l  e  .  t  x  t     \0

而不是正确的

2F 66 69 6C 65 2E 74 78 74 00 .... 00
/  f  i  l  e  .  t  x  t  \0

当尝试打印出此字符串时,您甚至不会看到空字符,就好像备用字节不存在一样,但对于系统来说,它很重要 C:

调用您提供的函数时,我得到这种输出

artyom@artyom:~/workspace/fopenfail$ ./a.out 
Strlen /file.txt = 10
Original path: /file.txt

Path after concatenating: ./file.txt
Error: No such file or directory


artyom@artyom:~/workspace/fopenfail$ ls
a.out  file.txt  main.c
artyom@artyom:~/workspace/fopenfail$ 

这是我用作示例的代码

void read_contents(char* file_path)
{
    printf("\nOriginal path: %s\n", file_path);

    // Trying to prefix the path with "." to indicate that the path is relative.
    char prefix[1024] = ".";

    strcat(prefix, file_path);

    // Printing to make sure that prefix contains correct path.
    printf("\nPath after concatenating: %s\n", prefix);

    FILE* file = fopen(prefix, "r");

    if (file == NULL)
    {
       perror("Error");

       // Close the file and stop the function.
       return;
    }


    // Code to read the file...
    // ...
    // Code to read the file...


    fclose(file);
}

int main()
{
        char path[] = "/file.txt";
        char path2[100] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x02};
        memcpy(path2, path, 9);
        printf("Strlen %s = %d", path2, strlen(path2));

        read_contents(path2);
        return EXIT_SUCCESS;
}

希望这能提示调用者函数中出了什么问题。

评论

0赞 Default 6/27/2023
哦,我的上帝,非常感谢你。我完全忘记了这一点。