C ++内存流到C文件流

时间:2017-09-29 15:39:19

标签: c++ c boost stl iostream

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

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

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

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

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

1 个答案:

答案 0 :(得分:5)

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

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