C 创建导致字符串的文件*流

C 创建导致字符串的文件*流,c,string,file,stream,printf,C,String,File,Stream,Printf,我正在寻找一种将文件*传递给某个函数的方法,以便该函数可以使用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

我正在寻找一种将
文件*
传递给某个函数的方法,以便该函数可以使用
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的glibc头似乎表示可以使用钩子函数设置文件,以执行实际的读写操作。在我的例子中,我想我希望write钩子将字符串的一个副本附加到一个链接列表中,并且有一个
get\u string\u buffer
函数,它计算出列表的总长度,为列表分配内存,然后将每个项复制到正确的位置

我的目标是可以传递给函数的东西,比如
do\u some\u stuff
,而该函数不需要知道除此之外的任何东西,它有一个
文件*
可以写入


有这样的实现吗?这似乎是一件有用且对C友好的事情——假设我对
文件
可扩展性的看法是正确的。

我不确定是否可以不可移植地扩展
文件
对象,但如果您正在寻找对POSIX更友好的东西,可以使用
管道
fdopen

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

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
,当另一端关闭管道时会发生这种情况。为了便于使用,您可能希望在单独的线程中执行缓冲区的
写入
,以避免阻塞,并确保处理
SIGPIPE


当然,这不会创建一个可查找的
文件*
..

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

但我不确定我是否理解您为什么要处理文件*。你不能简单地写一个文件,然后用字符串加载它吗

 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()
处理可扩展缓冲区(有关如何处理此问题的建议,请参阅此问题的答案:)


相反,如果您想创建一个类型,该类型可以透明地传递给任何使用
文件*
的函数,使它们作用于字符串缓冲区,那么这是一个更复杂的问题…

open\u memstream正是我想要的。我不确定它是否使用了链表方法,但我不会向它写入大量数据,所以这无关紧要。有很好的理由需要这样一个
文件*
:有许多库只提供基于
文件*
)的I/O,并且坚持读取文件,而数据可能已经存在于内存中。因此,我们希望能够传递内存缓冲区,而不是仅仅针对这些库将其写入文件。不幸的是,这些库很少(如果有的话)提供其依赖于
文件的API的替代方案。