从`FILE*`获取文件名的方法是什么?

16

可能重复:
从文件描述符中获取文件名(C语言)

有没有一种简单且(相对)可移植的方法可以从 FILE* 中获取文件名?

我使用 f = fopen(filename, ...) 打开一个文件,然后将 f 传递给其他各种函数,其中一些可能会报告错误。我想在错误消息中报告文件名,但避免传递额外的参数。

我可以创建一个自定义包装器 struct { FILE *f, const char *name },但也许有更简单的方法?(如果没有使用 fopen 打开 FILE*,我不关心结果。)


1
我不知道有标准的方法;freopen 可以让你改变读/写和二进制/普通模式,但如果你只是为了名字而需要它(比如打印错误信息),那么你就没办法了。 - dmckee --- ex-moderator kitten
1
我认为你不能这样做 - 对于那些具有指向相同inode的多个名称的文件怎么办?(在这种情况下没有“规范”文件名,两者都是有效的)那么对于那些不是真正的文件(如套接字等)呢? - Piskvor left the building
1
在https://dev59.com/93M_5IYBdhLWcg3w3nXz中回答了Linux的问题(您只需使用`fileno`从`FILE*`获取fd)。不过这并不是很便携。 - gnud
1
翻译:请注意,这个问题涉及stdio文件句柄而不是文件描述符,因此与问题1188757不重复。 - Nordic Mainframe
1
如果必须要可移植到posix,显然没有好的解决方案。还必须考虑到在许多文件系统中,同一个文件系统对象(相当于任何文件系统中的"inode")可能有多个名称(例如硬链接)。所以我认为与其让问题变得复杂,不如直接保存名称。 - sinelaw
显示剩余4条评论
2个回答

15

在某些平台上(如Linux),你可以通过读取/proc/self/fd/<number>的链接来获取它,像这样:

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

int main(void)
{
    char path[1024];
    char result[1024];

    /* Open a file, get the file descriptor. */
    FILE *f = fopen("/etc/passwd", "r");
    int fd = fileno(f); 

    /* Read out the link to our file descriptor. */
    sprintf(path, "/proc/self/fd/%d", fd);
    memset(result, 0, sizeof(result));
    readlink(path, result, sizeof(result)-1);

    /* Print the result. */
    printf("%s\n", result);
}

在我的系统上,这将打印出所需的/etc/passwd


它会在匿名管道上打印什么? - dmckee --- ex-moderator kitten
@dmckee: pipe:[<一些数字>] - intelfx

4

这有点困难,因为 FILE* 可以从一个与命名文件没有关联的文件句柄中读取/写入(例如未命名的管道或套接字)。您可以使用 fileno() 获取文件句柄,然后有系统特定的方法来了解文件名。下面是如何在 Linux 下执行此操作的讨论:

从文件描述符获取文件名

而在 Windows 下,这也不容易:

http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx (在这里,您需要使用 _get_osfhandle() 从 c 库文件描述符获取 Windows 文件句柄作为额外步骤)


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