创建导致字符串的FILE *流

我正在寻找一种方法将FILE *传递给某个函数,以便函数可以使用fprintf写入它。 如果我希望输出在磁盘上的实际文件中出现,这很容易。 但我想要的是将所有输出作为字符串( char * )。 我喜欢的那种API是:

 /** Create a FILE object that will direct writes into an in-memory buffer. */ FILE *open_string_buffer(void); /** Get the combined string contents of a FILE created with open_string_buffer (result will be allocated using malloc). */ char *get_string_buffer(FILE *buf); /* Sample usage. */ FILE *buf; buf = open_string_buffer(); do_some_stuff(buf); /* do_some_stuff will use fprintf to write to buf */ char *str = get_string_buffer(buf); fclose(buf); free(str); 

glibc标题似乎表明可以使用钩子函数设置FILE来执行实际的读写操作。 在我的情况下,我想我希望写钩子将字符串的副本附加到链表,并且有一个get_string_buffer函数,它计算出列表的总长度,为它分配内存,然后复制每个项目在正确的地方进入它。

我的目标是可以传递给do_some_stuff这样的函数,而不需要知道任何其他函数,除了它有一个它可以写入的FILE *

是否存在类似这样的现有实现? 这似乎是一个有用且C友好的事情 – 假设我对FILE可扩展性是正确的。

如果可移植性对您不重要,您可以查看fmemopen和open_memstream 。 它们是GNU扩展,因此仅在glibc系统上可用。 虽然看起来它们是POSIX.1-2008( fmemopen和open_memstream )的一部分。

我不确定是否可以非扩展地扩展FILE对象,但如果你正在寻找更多POSIX友好的东西,你可以使用pipefdopen

它与从缓冲区返回字节的FILE*不完全相同,但它肯定是具有编程确定内容的FILE*

 int fd[2]; FILE *in_pipe; if (pipe(fd)) { /* TODO: handle error */ } in_pipe = fdopen(fd[0], "r"); if (!in_pipe) { /* TODO: handle error */ } 

从那里你将需要使用write()将缓冲区写入fd[1] 。 但是,请小心这一步,因为如果管道的缓冲区已满(即有人需要读取另一端), write()可能会阻塞,如果您的进程在写入时获得信号,您可能会获得EINTR 。 还要注意SIGPIPE ,当另一端关闭管道时会发生这种情况。 也许为了您的使用,您可能希望在单独的线程中write缓冲区以避免阻塞并确保您处理SIGPIPE

当然,这不会创建一个可搜索的FILE*

我不确定我理解你为什么要搞乱FILE *。 你不能简单地写一个文件,然后加载到字符串中吗?

  char *get_file_in_buf(char *filename) { char *buffer; ... get file size with fseek or fstat ... ... allocate buffer ... ... read buffer from file ... return buffer; } 

如果您只想将格式化文本“写入”字符串,另一个选项可能是使用snprintf()处理可扩展缓冲区(请参阅此SO问题的答案以获取有关如何处理此问题的建议: 恢复[vf]?nprintf达到极限后 )。

相反,如果你想要创建一个可以透明地传递给任何函数的类型,它们使用FILE *来使它们对字符串缓冲区起作用,那么这是一个复杂得多的问题……