C++ 内存流到 C 文件流

C++ memory stream to C file stream

提问人:Ton van den Heuvel 提问时间:9/29/2017 更新时间:9/30/2017 访问量:2044

问:

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

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

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

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

另一种选择是解压缩内存中的所有数据,然后用于获取解压缩后的数据。这意味着我可能不得不分配大量数据,但我更希望看到一个缓冲解决方案。这有什么可能吗?fmemopenFILE*

C++ C 升压 STL IOstream

评论

0赞 Dale Wilson 9/29/2017
看看它可能会做你想做的事。open_memstream
0赞 Sneftel 9/29/2017
如果需要流式/缓冲数据,并且可能比 更好。pipefdopenfmemopen
0赞 jxh 9/30/2017
boost::zlib 有帮助吗?

答:

6赞 Antti Haapala -- Слава Україні 9/30/2017 #1

如果你使用的是 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,好吧,可怜的你

评论

0赞 Ton van den Heuvel 10/2/2017
对不起,我没有提到这一点,但幸运的是我在 Linux 上:)感谢您的回答,很棒的解决方案。