我正在寻找一种方法将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
可扩展性是正确的。
答案 0 :(得分:5)
如果可移植性对您不重要,您可以查看fmemopen和open_memstream。它们是GNU扩展,因此只能在glibc系统上使用。虽然看起来它们是POSIX.1-2008(fmemopen和open_memstream)的一部分。
答案 1 :(得分:2)
我不确定是否可以非扩展FILE
个对象,但如果您正在寻找更多POSIX友好的东西,可以使用pipe
和{{1} }。
与从缓冲区返回字节的fdopen
不完全相同,但它肯定是具有编程确定内容的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 */
}
将缓冲区写入fd[1]
。但是,请小心这一步,因为write()
可能会阻塞管道缓冲区已满(即有人需要读取另一端),如果您的进程在写入时获得信号,则可能会write()
。还要注意EINTR
,当另一端关闭管道时会发生这种情况。也许供您使用,您可能希望在单独的线程中执行缓冲区的SIGPIPE
以避免阻塞并确保处理write
。
当然,这不会创建一个可搜索的SIGPIPE
...
答案 2 :(得分:0)
我不确定我理解你为什么要搞乱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问题的答案:{ {3}})。
相反,如果你想创建一个可以透明地传递给任何函数的类型,使FILE *
使它们对字符串缓冲区起作用,那就更复杂了......