我有一个gzip文件" dat.gz",原始文件只包含逐行的ascii文本。 .gz文件由' pigz -i'
生成我想加载" dat.gz"进入几个进程并行数据处理。 程序语言必须是C或C ++。在Linux下
例如,原始文件包含" 1 \ n2 \ n3",我将.gz文件加载到3个进程(p0,p1,p2),以便p0得到" 1& #34;,p1得到" 2"和p3获得" 3"。
我在这里阅读了gz的文件格式:http://tools.ietf.org/pdf/rfc1952.pdf,我发现一个.gz文件的每个块都以" \ x1f \ x8b"开头。所以我用" \ x1f \ x8b"来剪切.gz文件。成块。但是当我使用boost的解压缩库来处理块时,出现了问题。
也许我的方法根本不对。
我的测试.gz文件可以在这里下载:https://drive.google.com/file/d/0B9DaAjBTb3bbcEM1N1c4OEg0SWc/view?usp=sharing
我的C ++测试代码如下。运行" g ++ -std = c ++ 11 test.cpp -lboost_iostreams&& ./a.out" ;.它抛出异常。
在抛出一个实例后终止调用 boost :: exception_detail :: clone_impl>' what():gzip错误 中止
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/copy.hpp>
#include <sstream>
//define buffer size of fread: 128KB
#define BUFSIZE 128*1024
void get_first_block(char *fn) {
FILE* fin = fopen(fn, "rb");
char buf[BUFSIZE] = {0};
int pos = 0;
//skip first 2 byte
fread(buf, sizeof(char), 2, fin);
int i;
while (1) {
int sz = fread(buf, sizeof(char), BUFSIZE, fin);
if (sz <= 1) {
break;
}
for (i=0; i<sz-1; ++i) {
if (buf[i] == (char)0x1f && buf[i+1] == (char)0x8b) {
break;
}
}
pos += sz;
}
//first block start: 0
//first block end: pos + i -1
int len = pos+i;
fseek(fin, 0, SEEK_SET);
char *blk = (char*)malloc(len);
fread(blk, 1, len, fin);
using namespace boost::iostreams;
filtering_streambuf<input> in;
in.push( gzip_decompressor() );
in.push( boost::iostreams::array_source(blk , len) );
std::stringstream _sstream;
boost::iostreams::copy(in, _sstream);
std::cout << _sstream.rdbuf() ;
}
int main() {
get_first_block("0000.gz");
return 0;
}
答案 0 :(得分:0)
.gz文件中不可能存在多个块,也请参阅the Wikipedia article about gzip:
虽然它的文件格式也允许多个这样的流 连接(压缩文件简单解压缩连接,就好像 它们原本是一个文件),gzip通常用于压缩 只是单个文件。
对于您的测试文件尤其如此,因为如果您另外查看&#34;压缩方法&#34; flag,你可以将搜索字符串扩展为0x1F,0x8B,0x08,它只在测试文件的最开头出现一次。
当尝试将.gz文件拆分为块时,您必须进行更多解析而不是仅查找0x1F,0x8B,因为这也可能出现在压缩数据块或成员的其他部分中。
您必须解析成员和压缩数据。不幸的是,标题只包含未压缩的数据长度,而不是压缩长度,所以你不能跳过压缩数据而不解析它。
压缩数据将是deflate数据(还有其他但未使用的压缩类型),请参阅RFC 1951。对于非压缩放气块(第3.2.4节),标题中有LEN
字段,因此您可以轻松跳过这些字段。但遗憾的是,压缩块的标题中没有长度字段,因此您必须完全解析这些字段。
答案 1 :(得分:0)
pigz -i
独立压缩每个块,允许在每个块边界进行随机访问。每个块之间是一个空的存储块,以字节序列00 00 ff ff
结束。您可以搜索该序列,然后尝试解压缩。您的示例文件中有39个这样的标记。
没有任何东西阻止00 00 ff ff
出现在压缩块的中间,而不是标记块边界。所以你应该期望偶尔会得到这样一个边界的错误指示,表示没有解压缩。在这种情况下,只需转到下一个这样的标记。