使用提升和过滤流解压缩档案 [英] Decompressing archives with boost and filtering streams

查看:71
本文介绍了使用提升和过滤流解压缩档案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在解压缩大型文件,其中包含以各种方式包含压缩数据的指定块。
我编写了以下代码:

  // input_file-文件
std :: ifstream文件的路径(input_file,std :: ios_base :: in | std :: ios_base :: binary);
//移动到第n个数据块的开头,由zlib
文件压缩.seekg(offset,std :: ios_base :: beg);
boost :: iostreams :: filtering_streambuf< boost :: iostreams :: input>在;
in.push(boost :: iostreams :: zlib_decompressor());
in.push(file);
//将解压缩的数据写入输出文件
boost :: iostreams :: copy(in,output);

我的理解是这条线

  boost :: iostreams :: copy(输入,输出); 

将开始解压缩和复制数据,直到文件结尾,在这种情况下是不需要的。 / p>

重要的是,我知道压缩数据的正确偏移量和长度。



Boost文档指出:



Source的模型可定义如下:

  struct来源{
typedef char char_type;
typedef source_tag类别;
std :: streamsize read(char * s,std :: streamsize n)
{
//从输入
//读取最多n个字符//进入缓冲区s ,返回
//读取的字符数,或-1
//表示序列结束。
}
};

我想从ifstream类继承,覆盖它为read方法,然后在该方法内部计算多少字节被读取,如果该块中没有更多数据,则返回-1,但是不幸的是,它似乎无法正常工作。



我写道:

  class ifstream_t:public std :: ifstream {
public:
ifstream_t(const std :: string& fp,std :: ios_base: :openmode mode = std :: ios_base :: in):std :: ifstream(fp,mode){}
std :: streamsize read(char * s,std :: streamsize n){
/ /计算剩余字节
返回-1;
}
};

并将其用于:

  ifstream_t文件(this-> fp,std :: ios_base :: in | std :: ios_base :: binary); 
boost :: iostreams :: filtering_streambuf< boost :: iostreams :: input>在;
in.push(boost :: iostreams :: zlib_decompressor());
in.push(file);
boost :: iostreams :: copy(输入,输出);

从我的类中读取的方法未调用。

解决方案


我的理解是这一行

  boost :: iostreams :: copy(输入,输出); 

将开始解压缩和复制数据,直到文件结尾,在这种情况下是不需要的。 / p>

我刚刚测试过了,事实并非如此。当压缩数据完成时,解压缩器会正确检测到流的结尾。



我创建了一个文件,其中包含一些随机数据,这些数据夹在其自己的压缩源中:¹

 (dd if = / dev / urandom bs = 1 count = $(((0x3214a))); cat main.cpp | zlib-flate -compress; dd if = / dev / urandom bs = 1 count = $((0x3214a)))> input.txt 

在使用带有硬编码偏移量的程序和该文件时:



在Coliru上直播

  #include< boost / iostreams / filter / zlib.hpp> 
#include< boost / iostreams / filtering_streambuf.hpp>
#include< boost / iostreams / copy.hpp>
#include< fstream>
#include< iostream>

int main(){
static std :: string const input_file = input.txt;
static size_t const offset = 0x3214a;
std :: ostream&输出= std :: cout;

// input_file-文件
的路径std :: ifstream文件(input_file,std :: ios_base :: in | std :: ios_base :: binary);

//移动到第n个数据块的开头,由zlib
文件压缩.seekg(offset,std :: ios_base :: beg);
boost :: iostreams :: filtering_streambuf< boost :: iostreams :: input>在;

in.push(boost :: iostreams :: zlib_decompressor());
in.push(file);

//将解压缩后的数据写入输出文件
boost :: iostreams :: copy(in,output);
}

很高兴复制自己的资源,就像在大肠杆菌上看到的一样






¹coliru上没有zib-flate,所以我用python:

  python -c'导入zlib;进口系统; sys.stdout.write(zlib.compress(sys.stdin.read()))’


I am working on decompressing large files, with contains specified blocks of compressed data various ways. I wrote a following code:

// input_file - path to file
std::ifstream file(input_file, std::ios_base::in | std::ios_base::binary);
//move to begin of n-th data block, compressed by zlib
file.seekg(offset, std::ios_base::beg);
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(file);
// write decompressed data to output file
boost::iostreams::copy(in, output);

My understanding is this line

boost::iostreams::copy(in, output); 

will start decompressing and copying data until the end of the file, which is unwanted in that case.

It is important that, I know the proper offset and length of compressed data.

Boost documentation says that:

A model of Source can be defined as follows:

struct Source {
    typedef char        char_type;
    typedef source_tag  category;
    std::streamsize read(char* s, std::streamsize n) 
    {
        // Read up to n characters from the input 
        // sequence into the buffer s, returning   
        // the number of characters read, or -1 
        // to indicate end-of-sequence.
    }
};

I wanted to inherit from ifstream class, overwrite it read method, and inside that method calculate how many bytes were read and return -1 if there is no more data in that chunk, but unfortunately, it seems not working.

I wrote:

class ifstream_t : public std::ifstream{
     public:
     ifstream_t(const std::string& fp, std::ios_base::openmode mode = std::ios_base::in) : std::ifstream(fp, mode){}
     std::streamsize read(char* s, std::streamsize n) {
         // calculate remaining bytes 
         return -1;
     }   
};

and used it in:

ifstream_t file(this->fp, std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(file);
boost::iostreams::copy(in, output);

method read, from my class in not invoked.

解决方案

My understanding is this line

 boost::iostreams::copy(in, output);

will start decompressing and copying data until the end of the file, which is unwanted in that case.

I just tested this, and that's not the case. The decompressor correctly detects the end of stream when the compressed data is completed.

I created a file with some random data sandwiching its own compressed source:¹

(dd if=/dev/urandom bs=1 count=$((0x3214a)); cat main.cpp | zlib-flate -compress; dd if=/dev/urandom bs=1 count=$((0x3214a))) > input.txt 

When using the program with hardcoded offset and that file:

Live On Coliru

#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <fstream>
#include <iostream>

int main() {
    static std::string const input_file = "input.txt";
    static size_t      const offset     = 0x3214a;
    std::ostream& output = std::cout;

    // input_file - path to file
    std::ifstream file(input_file, std::ios_base::in | std::ios_base::binary);

    //move to begin of n-th data block, compressed by zlib
    file.seekg(offset, std::ios_base::beg);
    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;

    in.push(boost::iostreams::zlib_decompressor());
    in.push(file);

    // write decompressed data to output file
    boost::iostreams::copy(in, output);
}

Which happily reproduces its own source, as you can see live on coliru


¹ zib-flate is absent on coliru, so I used python:

python -c 'import zlib; import sys; sys.stdout.write(zlib.compress(sys.stdin.read()))'

这篇关于使用提升和过滤流解压缩档案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆