提问人:Ton van den Heuvel 提问时间:9/29/2017 更新时间:9/30/2017 访问量:2044
C++ 内存流到 C 文件流
C++ memory stream to C file stream
问:
给定一个 C++ 输入内存流,是否可以直接将数据从该流写入 C 文件流 (),而不必先将数据写入磁盘?std::istream
FILE*
我问的原因是我有一个 C 接口,需要 ,我想透明地支持压缩或未压缩的输入文件。FILE*
这个想法是编写一个包装函数,该函数接受输入文件,然后用于创建一个过滤流,该流在必要时进行解压缩,然后以某种方式将解压缩后的数据转发到 C API。boost::iostreams
最简单的方法是解压缩压缩文件,将解压缩后的数据写入磁盘,然后写入临时文件。不过,我想防止必须创建临时文件。fopen
另一种选择是解压缩内存中的所有数据,然后用于获取解压缩后的数据。这意味着我可能不得不分配大量数据,但我更希望看到一个缓冲解决方案。这有什么可能吗?fmemopen
FILE*
答:
如果你使用的是 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,好吧,可怜的你。
评论
open_memstream
pipe
fdopen
fmemopen