Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何分布式加载GZIP文件?_C++_Gzip - Fatal编程技术网

C++ 如何分布式加载GZIP文件?

C++ 如何分布式加载GZIP文件?,c++,gzip,C++,Gzip,我有一个gzip文件“dat.gz”,源文件只逐行包含ascii文本该.gz文件由'pigz-i'生成。 我想将“dat.gz”加载到多个进程中以进行并行数据处理我的C++测试代码正在执行。通过“g++-std=c++11 test.cpp-lboost_iostreams&&./a.out”运行。它抛出了一个异常 在抛出的实例后调用terminate boost::异常\u详细信息::克隆\u impl>' 什么():gzip错误 流产 #包括 #包括 #包括 #包括 #包括 #包括 #包括

我有一个gzip文件“dat.gz”,源文件只逐行包含ascii文本该.gz文件由'pigz-i'生成。

我想将“dat.gz”加载到多个进程中以进行并行数据处理<程序语言必须是C或C++。在Linux下

例如,源文件包含“1\n2\n3”,我将.gz文件加载到3个进程(p0、p1、p2)中,以便p0获得“1”,p1获得“2”,p3获得“3”

我在这里阅读了gz的文件格式:,发现一个.gz文件的每个块都以“\x1f\x8b”开头。因此,我将“\x1f\x8b”的.gz文件剪切成块。但是,当我使用boost的解压库来处理块时,出现了一些问题

也许我的方法根本是错的

我的test.gz文件可以在这里下载:

< >我的C++测试代码正在执行。通过“g++-std=c++11 test.cpp-lboost_iostreams&&./a.out”运行。它抛出了一个异常

在抛出的实例后调用terminate boost::异常\u详细信息::克隆\u impl>' 什么():gzip错误 流产

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//定义fread的缓冲区大小:128KB
#定义BUFSIZE 128*1024
void get_first_块(char*fn){
文件*fin=fopen(fn,“rb”);
char buf[BUFSIZE]={0};
int pos=0;
//跳过前2字节
fread(buf,sizeof(char),2,fin);
int i;
而(1){
int sz=fread(buf,sizeof(char),BUFSIZE,fin);

如果(sz一个.gz文件中不可能有多个块,请参见:

虽然它的文件格式也允许多个这样的流 连接(压缩文件只是解压连接,就像 它们最初是一个文件),gzip通常用于压缩 只有一个文件

对于您的测试文件尤其如此,因为如果您另外查看“compression method”标志,您可以将搜索字符串扩展到0x1F、0x8B、0x08,该字符串仅在测试文件的最开始出现一次

当尝试将.gz文件拆分为块时,必须进行更多的解析,而不是只查找0x1F、0x8B,因为这也可能出现在压缩数据块或成员的其他部分中

您必须解析成员和压缩数据。不幸的是,标头只包含数据的未压缩长度,而不是压缩长度,因此您不能跳过压缩数据而不进行解析


压缩数据将为放气数据(有其他但未使用的压缩类型),参见。非压缩放气块(第3.2.4章),标头中有一个
LEN
字段,因此您可以轻松跳过这些字段。但不幸的是,在压缩块的标头中没有长度字段,因此您必须完全解析这些字段。

pigz-i
独立压缩每个块,这允许在每个块边界处进行随机访问。每个块之间是一个空的stored块,以字节序列结尾。您可以搜索该序列,然后尝试解压缩。示例文件中有39个这样的标记


<> P>没有什么可以防止<代码> 00 00 FF F/<代码>出现在压缩块的中间,而不是标记块边界。因此,您应该期望偶尔会得到一个错误的指示,这种边界是由解压缩失败表示的。在这种情况下,只需移动到下一个这样的标记。压缩是应用程序的瓶颈?如果只让一个进程将整个文件解压到一个共享内存区域中,其他所有进程都可以从该区域读取,则会容易得多。@5gon12eder但是如果.gz文件大小约为10GB?我假设某个进程同时需要所有数据。当然,如果您不能如果无法将整个解压文件放入内存,此解决方案就不太好,除非您希望超级乐观,并希望操作系统能够高效地进行交换。工作进程中的数据访问模式如何?是否可以使用“解压线程”要在解压数据运行时对其进行分块,并且只向工作程序发送分块(可能通过MPI)?工作程序将在接收下一个分块时处理前一个分块。
#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;
}