2009-11-16 37 views
5

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

/** 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头似乎表明,一个文件可能被设置了挂钩函数来执行实际的读写。在我的情况下,我想我希望写钩子将一个字符串的副本附加到一个链表中,并且要有一个函数来计算列表的总长度,为它分配内存,然后复制每个项目进入正确的地方。

我瞄准的东西,可以传递给一个功能,如do_some_stuff没有该功能需要知道任何东西,但它有一个FILE *它可以写入。

有没有像这样的现有实现?这似乎是一个有用的和C友好的事情要做 - 假设我是对的FILE扩展性。

回答

5

如果可移植性不是重要的是你,你可以采取fmemopenopen_memstream看看。它们是GNU扩展,因此只能在glibc系统上使用。尽管它看起来像是POSIX.1-2008(fmemopenopen_memstream)的一部分。

+0

open_memstream正是我想要的。我不确定它是否使用链表方式,但我不会为它编写大量数据,因此无关紧要。 – Edmund 2009-11-16 19:32:34

2

我不知道是否有可能以非便携扩展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* ...

+0

+1谈好解释需要一个单独的线程 – Andomar 2009-11-16 10:50:26

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()(见的答案,这太问题上如何处理这个建议来处理可扩展缓冲:Resuming [vf]?nprintf after reaching the limit )。

相反,如果你想创建一个可以透明地传递给任何函数采取FILE *,使他们在字符串缓冲区扮演一个类型,它是一个更复杂的事情......

+0

想要这样一个'FILE *'有很好的理由:有很多库只提供基于FILE *的I/O,并且当数据可能已经在内存中可用时,坚持读取一个文件。因此,希望能够传递内存缓冲区,而不是只为这些库写出文件。不幸的是,这些库很少,如果有的话,提供替代他们的'FILE *' - 依赖API。 – greyfade 2011-10-06 17:54:18