创建导致字符串的FILE *流

时间:2009-11-16 10:01:31

标签: c string file stream printf

我正在寻找一种方法将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可扩展性是正确的。

3 个答案:

答案 0 :(得分:5)

如果可移植性对您不重要,您可以查看fmemopenopen_memstream。它们是GNU扩展,因此只能在glibc系统上使用。虽然看起来它们是POSIX.1-2008(fmemopenopen_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 *使它们对字符串缓冲区起作用,那就更复杂了......