【问题标题】:"fprintf"-like function for file descriptors (i.e. int fd instead of FILE* fp)类似“fprintf”的文件描述符函数(即 int fd 而不是 FILE* fp)
【发布时间】:2010-11-22 14:43:44
【问题描述】:

也许我只是想念它,但是否没有与 fprintf 等效的文件描述符功能,甚至没有一种在它们之间临时翻转的方法?

【问题讨论】:

    标签: c file-io printf posix-api


    【解决方案1】:

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

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

    编辑正如你们中的几位在 cmets 中指出的,POSIX 2008 标准化了这些函数。

    【讨论】:

    • 谢谢!非常有趣,不知道那些存在。
    • 我也没有。因为这个应用程序只能在 Linux 上运行,所以这可能是我需要的。跨平台兼容性不是问题,所以使用 GNU 扩展应该没问题。
    • 如果不关心可移植性,请选择这些。
    • 确实,POSIX 2008 标准化了这些函数。
    【解决方案2】:

    没有 C 或 POSIX(编辑:2008 年之前)标准函数可以对文件描述符执行 printf,但您可以使用 POSIX 标准 fdopen(int desc, const char *mode) “打开”文件描述符为 FILE * .我不确定直接返回使用描述符的支持有多好,但我猜如果你先刷新缓冲区,它可能会起作用……

    当然,您可以使用 vsprintf 之类的东西来实现自己的,但显然您必须注意缓冲。

    【讨论】:

    • 我在考虑 fdopen,但真的不想“打开”另一个句柄,特别是因为 IIRC 在该句柄上调用 fclose 也会关闭底层文件描述符。这将是我正在处理的代码的问题,因为例程可能会获取文件描述符或套接字句柄。
    • @Will:你可以fdopen处理从dup得到的文件,这样关闭不会影响你原来的fd
    • @Hasturkun:没错,我忘了 dup。不是我经常使用的那些功能之一。
    【解决方案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 * 例程那样缓冲;我更多的是寻找格式说明符和构建将写入文件描述符的字符数据的能力,而不是担心在写入数据时缓冲数据。

    【讨论】:

    • dprintf 是 POSIX(截至 2008 年),并且静默截断数据的函数通常是一个非常糟糕的主意。至少循环使用更大的缓冲区,直到它成功或返回失败......
    • 这很酷。我这里的 gcc 版本有点旧,但仍然显示 dprintf 只是一个 GNU 扩展。
    【解决方案4】:

    不,没有标准,但两者做不同的事情。 fprinft 作为 stdio 的一部分,执行缓冲区读取和写入等操作,支持 ungetc 等。使用 fd 绕过所有这些并直接调用操作系统。

    所以它们不可互换。如果不出意外,它们之间的翻转会搞砸 stdio 缓冲

    【讨论】:

    • 我是这么想的,但不是 100% 确定。
    • 除了...您可以使用fdopen,只要您记得在需要时发送flush(),触发器就可以正常工作。
    • 可能,但不能保证,如果您寻求不同的职位,可能无法正常工作,并且...
    【解决方案5】:

    您可以将文件描述符作为普通文件打开,该文件可由fprintf()fdopen 处理。

    【讨论】:

    • 刚刚发现dprintf up-thread 看起来很有趣,但读到这里让我想到:将fd 传递给函数并调用fdopen(fd) 会有多糟糕每个函数调用,如果性能不是问题?我想象这至少会像疯了一样泄漏内存。 (还有一些实现差异需要考虑,可能有些实现会泄漏,有​​些则不会。)或者这工作吗?
    猜你喜欢
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    • 2015-01-04
    • 2010-12-08
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    相关资源
    最近更新 更多