使用提升和过滤流解压缩档案 [英] Decompressing archives with boost and filtering streams
问题描述
我正在解压缩大型文件,其中包含以各种方式包含压缩数据的指定块。
我编写了以下代码:
// 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
在使用带有硬编码偏移量的程序和该文件时:
#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:
#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屋!