【问题标题】:C++ memory stream to C file streamC++ 内存流到 C 文件流
【发布时间】:2018-03-11 13:40:02
【问题描述】:

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

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

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

直接的方法是解压压缩文件,将解压后的数据写入磁盘,然后fopen临时文件。不过,我想避免创建临时文件。

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

【问题讨论】:

  • 看看open_memstream它可能会做你想做的事。
  • 如果您想要流式传输/缓冲数据,pipefdopen 可能比 fmemopen 更好。
  • boost::zlib 有帮助吗?

标签: c++ c boost stl iostream


【解决方案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,那么,poor you

【讨论】:

  • 对不起,我没有提到这一点,但幸运的是我在 Linux 上 :) 感谢您的回答,很好的解决方案。
猜你喜欢
  • 2010-10-21
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-05
  • 1970-01-01
相关资源
最近更新 更多