给定C ++ std::istream
输入内存流,是否可以直接将数据从该流直接写入C文件流(FILE*
)而不必先将数据写入磁盘? / p>
我问的原因是我有一个C接口采用FILE*
,我希望透明地支持压缩或未压缩的输入文件。
我们的想法是编写一个包含输入文件的包装函数,然后使用boost::iostreams
创建一个过滤流,必要时进行解压缩,然后以某种方式将解压缩的数据转发到C API。
直接的方法是解压缩压缩文件,将解压缩的数据写入磁盘,然后fopen
临时文件。我想防止必须创建临时文件。
另一种选择是解压缩内存中的所有数据,然后使用fmemopen
获取解压缩数据的FILE*
。这意味着我可能不得不分配大量数据,我宁愿看一个缓冲的解决方案。这有可能吗?
答案 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。