针对文件描述符(即int fd而非FILE* fp)的类似于“fprintf”的函数

21

也许我只是看漏了,但是是否存在一种类似于fprintf函数的文件描述符等效函数,或者甚至可以在它们之间临时切换的方法?

5个回答

32
您可以查看 dprintfGNU扩展,不在C或POSIX中):

dprintf()和vdprintf()函数(在glibc2库中找到)是fprintf()和vfprintf()的完全类似物,除了它们输出到文件描述符fd而不是给定流。

编辑: 正如您在评论中指出的那样,POSIX 2008标准化了这些功能。

谢谢!非常有趣,我不知道那些存在。 - Prof. Falken
我也没有。由于这个应用程序只会在Linux上运行,这可能是我需要的。跨平台兼容性不是一个问题,因此使用GNU扩展应该没问题。 - Will
如果可移植性不是问题,就选择这些。 - Arkku
2
的确,POSIX 2008标准化了这些函数。 - R.. GitHub STOP HELPING ICE

9

在2008年之前,C语言或POSIX标准中没有提供将printf输出到文件描述符的函数,但是你可以使用POSIX标准的fdopen(int desc, const char *mode)函数将文件描述符转换成FILE *。如果事先清空缓存,我不确定直接切换回使用文件描述符的支持情况如何。

当然你也可以自己实现,比如使用vsprintf,但是此时需要处理缓存问题。


1
我在考虑使用fdopen,但真的不想“打开”另一个句柄,特别是因为如果我IRC在该句柄上调用fclose,它也会关闭底层文件描述符。对于我正在处理的代码来说,这将是一个问题,因为该例程可能会得到一个文件描述符或套接字句柄。 - Will
5
你可以使用fdopen函数打开一个由dup获得的文件句柄,这样关闭操作就不会影响到你原来的文件句柄。 - Hasturkun
1
@Hasturkun:没错,我忘记了dup。这不是我经常使用的函数之一。 - Will

3

就算价值不高,由于dprintf不是POSIX函数,如果可移植性成为问题,可以使用以下方法:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>

int
fdprintf ( int fd, size_t bufmax, const char * fmt, ... )
{
  char * buffer;
  int n;
  va_list ap;

  buffer = ( char * ) malloc ( bufmax );
  if ( !buffer )
    return 0;

  va_start ( ap, fmt );
  n = vsnprintf ( buffer, bufmax, fmt, ap );
  va_end ( ap );

  write ( fd, buffer, n );
  free ( buffer );
  return n;
}

很可能需要检查write的返回值,但你已经有了一般的想法。显然,这不像FILE *例程那样缓冲;我更关注格式说明符和构建将写入文件描述符的字符数据的能力,而不是担心在写入数据时缓冲数据。


3
dprintf是POSIX标准(截至2008年),默默截断数据的函数通常是一个非常糟糕的想法。至少要使用较大的缓冲区循环直到成功,或返回失败... - R.. GitHub STOP HELPING ICE
很酷。我的gcc版本有点老,仍然将dprintf显示为仅GNU扩展。 - Will

2
没有标准的方法,但这两者有不同的功能。stdio中的fprinft可以进行缓冲读写,支持ungetc等操作。而使用fd则可以绕过所有这些并直接调用操作系统。
因此它们不能互换。如果反复切换它们,那么stdio的缓冲将会出现问题。

这正是我所想,但并不百分之百确定。 - Will
除了...你可以使用fdopen,并且只要在需要时记得调用flush(),翻转操作就能正常工作。 - Conrad Meyer
可能的,但不保证,如果您寻求不同的位置,可能无法正常工作,而且... - The Archetypal Paul

2

您可以使用fdopen将文件描述符打开为普通文件,然后可以使用fprintf()处理。


刚刚发现了上面的 dprintf,看起来很有趣,但是读到这里我想到了一个问题:如果不考虑性能,每次函数调用时将 fd 传递给一个函数并调用 fdopen(fd),会有多糟糕呢?我想象中这可能会导致内存泄漏。 (然后还要考虑实现差异,也许某些实现会泄漏而某些实现则不会。)或者这样做是可行的吗? - i336_

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