2009-11-16 35 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