能否使用boost iostreams实现即时读取和压缩gzip文件?

6

我正在使用boost iostreams读取一个gzipped文件:

以下代码可以正常工作:

 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);

然而,我不希望读入整个压缩文件占用内存。我希望能够逐步读取文件。
例如,如果我有一个数据结构X,它可以从istream中初始化自己。
X x;
x.read(in);

失败了。可能是因为我们需要将字符放回到流中,如果我们正在进行部分流处理。有没有想法,是否boost iostreams支持此功能?


像调用getline()然后通过循环进行compressing()这样的操作对您有用吗? - user99545
@user99545:不行,因为X是由二进制数据创建的。 - ATemp
我认为没有问题。在这种情况下,我已经使用了boost iostreams来读取和写入zlib压缩流。 - Ferruccio
这个回答解决了你的问题吗?https://dev59.com/uG7Xa4cB1Zd3GeqPlQur - Avneesh
2个回答

1

我认为你需要编写自己的过滤器。例如,要读取.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);

1
根据 iostream 文档,类型 boost::io::filtering_istream 派生自 std::istream。也就是说,应该可以在任何需要 std::istream& 的地方传递它。如果您在运行时出现错误,因为您需要 unget()putback() 字符,您应该查看 pback_size 参数,该参数指定最多返回多少个字符。我没有在文档中看到此参数的默认值。
如果这不能解决您的问题,您能否描述一下您的问题是什么?从外观上看,它应该可以工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接