可以提高iostream读取和压缩gzip文件的速度

Can boost iostreams read and compress gzipped files on the fly?

本文关键字:gzip 压缩 文件 速度 读取 iostream      更新时间:2023-10-16

我正在使用boost iostreams读取一个gzip文件:以下操作很好:

 namespace io = boost::iostreams;
  io::filtering_istream in;
  in.push(boost::iostreams::basic_gzip_decompressor<>());
  in.push(io::file_source("test.gz"));
  stringstream ss;
  copy(in, ss);

然而,我不想因为读取整个gzip文件而占用内存进入内存。我希望能够增量地读取该文件。

例如,如果我有一个数据结构X,它从istream,初始化自己

X x;
x.read(in);

失败。大概这是因为我们可能不得不将角色放回流中如果我们正在进行部分流。有没有关于boost iostreams是否支持这一点的想法?

根据iostream文档,类型boost::io::filtering_istream源自std::istream。也就是说,应该可以将其传递到期望std::istream&的任何地方。如果由于需要unget()putback()字符而在运行时出现错误,则应查看指定最多返回多少字符的pback_size参数。我还没有在文档中看到这个参数的默认值是什么

如果这不能解决你的问题,你能描述一下你的问题到底是什么吗?从外观上看应该是可行的。

我认为您需要编写自己的过滤器。例如,为了读取.tar.gz并输出包含的文件,我写了一些类似的东西

//using namespace std;
namespace io = boost::iostreams;
struct tar_expander
{
    tar_expander() : out(0), status(header)
    {
    }
    ~tar_expander()
    {
        delete out;
    }
    /* qualify filter */
    typedef char char_type;
    struct category :
        io::input_filter_tag,
        io::multichar_tag
    { };
    template<typename Source>
    void fetch_n(Source& src, std::streamsize n = block_size)
    {
           /* my utility */
           ....
    }
    // Read up to n filtered characters into the buffer s,
    // returning the number of characters read or -1 for EOF.
    // Use src to access the unfiltered character sequence
    template<typename Source>
    std::streamsize read(Source& src, char* s, std::streamsize n)
    {
      fetch_n(src);
      const tar_header &h = cast_buf<tar_header>();
      int r;
      if (status == header)
      {
          ...
      }
      std::ofstream *out;
      size_t fsize, stored;
      static const size_t block_size = 512;
      std::vector<char> buf;
      enum { header, store_file, archive_end } status;
   }
}

我的函数read(Source &...)在被调用时接收解压缩的文本。使用过滤器:

ifstream file("/home/..../resample-1.8.1.tar.gz", ios_base::in | ios_base::binary);
io::filtering_streambuf<io::input> in;
in.push(tar_expander());
in.push(io::gzip_decompressor());
in.push(file);
io::copy(in, cout);