C++内存流到C文件流

Ton*_*vel 2 c c++ boost iostream stl

给定C++ std::istream输入内存流,是否可以直接将数据从该流写入C文件流(FILE*)而无需先将数据写入磁盘?

我问的原因是我有一个C接口FILE*,我希望透明地支持压缩或未压缩的输入文件.

我们的想法是编写一个包装函数来获取输入文件,然后用于boost::iostreams创建一个过滤流,必要时进行解压缩,然后以某种方式将解压缩的数据转发到C API.

直接的方法是解压缩压缩文件,将解压缩的数据写入磁盘,然后写入fopen临时文件.我想防止必须创建临时文件.

另一种选择是解压缩内存中的所有数据,然后用于fmemopen获取FILE*解压缩的数据.这意味着我可能不得不分配大量数据,我宁愿看一个缓冲的解决方案.这有可能吗?

Ant*_*ala 6

如果您使用的是GNU系统(Linux,Glibc),则可以使用为解码操作fopencookie创建FILE *包装器:

FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs);
Run Code Online (Sandbox Code Playgroud)

[...]

fopencookie()函数用于类似于fopen(3)的目的:它打开一个新流并返回一个指向FILE对象的指针,该对象用于对该流进行操作.

cookie参数是指向调用者的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;
Run Code Online (Sandbox Code Playgroud)

[...]

(我不想将整个联机帮助页复制到我的答案中).

基本上你可以这样做:

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);
Run Code Online (Sandbox Code Playgroud)

在BSD/OSX上,你也同样幸运,因为它funopen只是一个稍微不同的API来实现完全相同的东西.

如果你想支持Windows,那么,你可怜.