2017-09-29 79 views
1

給定一個C++ std::istream輸入內存流,是否可以以任何方式直接將該流中的數據寫入C文件流(FILE*),而無需先將數據寫入磁盤?將C++內存流轉換爲C文件流

我問的原因是我有一個C接口採取FILE*,爲此我想透明地支持壓縮或未壓縮的輸入文件。

這個想法是編寫一個包裝函數,它接受輸入文件,然後使用boost::iostreams創建一個過濾流,在必要時執行解壓縮,然後將解壓縮的數據以某種方式轉發給C API。

直接的方法是解壓縮壓縮文件,將解壓後的數據寫入磁盤,然後將臨時文件寫入fopen。我想阻止不得不創建臨時文件。

另一種選擇是解壓縮內存中的所有數據,然後使用fmemopen獲得解壓縮數據的FILE*。這意味着我可能必須分配大量數據,但我希望看到緩衝解決方案。這是可能的嗎?

+0

看看'open_memstream'它可以做你想做的事。 –

+0

如果你想流/緩衝數據,'pipe'和'fdopen'可能比'fmemopen'好。 – Sneftel

+0

[boost :: zlib](http://www.boost.org/doc/libs/release/libs/iostreams/doc/classes/zlib.html)有幫助嗎? – jxh

回答

4

如果你是一個GNU系統,(Linux操作系統,Glibc的),你可以使用fopencookie創建FILE *包裝爲您解碼操作:

FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs); 

[...]

fopencookie()函數的用途與fopen(3)相似:它打開一個新流並返回一個指向FILE對象的指針,該對象用於在該流上操作。

cookie參數是指向要與新流關聯的調用者的Cookie結構 的指針。當標準I/O庫調用 下面描述的任何鉤子函數時,該指針是作爲第一個參數提供的 。

mode參數的作用與fopen(3)相同。支持以下模式的 :r,w,a,r +,w +和a +。有關詳細信息,請參閱fopen(3) 。

的io_funcs參數是包含四個字段 指向該用於 實現此流程序員定義鉤的功能的結構。該結構的定義如下

typedef struct { 
    cookie_read_function_t *read; 
    cookie_write_function_t *write; 
    cookie_seek_function_t *seek; 
    cookie_close_function_t *close; 
} cookie_io_functions_t; 

[...]

(我不想給整個手冊頁拷貝到我的答案)。

基本上,你可以這樣做:

ssize_t my_read(void *cookie, char *buf, size_t size) { 
    std::istream *the_stream = static_cast<std::istream*>(cookie); 
    // insert magic 
    return bytes_read; 
} 

cookie_io_functions_t my_functions = { 
    my_read, 
    NULL, 
    NULL, 
    NULL, 
}; 

... 

FILE *wrapped = fopencookie(static_cast<void *>&stream, "rb", my_functions); 

在BSD/OSX,你會同樣幸運的,因爲它帶有funopen這僅僅是一個略有不同的API來實現同樣的事情。

如果你想支持Windows,那麼,poor you

+0

對不起,我沒有提到這一點,但幸運的是我在Linux上:)謝謝你的答案,很好的解決方案。 –