如何将boost::iostreams::mapped_file_source与gzip输入文件一起使用

how to use boost::iostreams::mapped_file_source with a gzipped input file

本文关键字:输入 gzip 文件 一起 file boost iostreams mapped source      更新时间:2023-10-16

我使用boost::iostreams::mapped_file_source将文本文件从特定位置读取到特定位置,并操作每一行(使用g++ -Wall -O3 -lboost_iostreams -o test main.cpp编译):

#include <iostream>
#include <string>
#include <boost/iostreams/device/mapped_file.hpp>
int main() {
boost::iostreams::mapped_file_source f_read;
f_read.open("in.txt");
long long int alignment_offset(0);
// set the start point
const char* pt_current(f_read.data() + alignment_offset);
// set the end point
const char* pt_last(f_read.data() + f_read.size());
const char* pt_current_line_start(pt_current);
std::string buffer;
while (pt_current && (pt_current != pt_last)) {
if ((pt_current = static_cast<const char*>(memchr(pt_current, 'n', pt_last - pt_current)))) {
buffer.assign(pt_current_line_start, pt_current - pt_current_line_start + 1);
// do something with buffer
pt_current++;
pt_current_line_start = pt_current;
}
}
return 0;
}

目前,我想让这段代码也能处理gzip文件,并像这样修改代码:

#include<iostream>
#include<boost/iostreams/device/mapped_file.hpp>
#include<boost/iostreams/filter/gzip.hpp>
#include<boost/iostreams/filtering_streambuf.hpp>
#include<boost/iostreams/filtering_stream.hpp>
#include<boost/iostreams/stream.hpp>
int main() {
boost::iostreams::stream<boost::iostreams::mapped_file_source> file;
file.open(boost::iostreams::mapped_file_source("in.txt.gz"));
boost::iostreams::filtering_streambuf< boost::iostreams::input > in; 
in.push(boost::iostreams::gzip_decompressor());
in.push(file);
std::istream std_str(&in);
std::string buffer;
while(1) {
std::getline(std_str, buffer);
if (std_str.eof()) break;
// do something with buffer
}   
}   

这段代码也能很好地工作,但我不知道如何像第一段代码一样设置起点(pt_current)和终点(pt_last)。你能告诉我如何在第二段代码中设置这两个值吗?

答案是否定的,这是不可能的。压缩流需要有索引。


真正的问题是为什么。您正在使用内存映射文件。动态压缩/解压缩只会降低性能并增加内存消耗。

如果你不缺乏实际的文件存储,那么你可能应该考虑二进制表示,或者保持文本原样

当使用随机访问的文本文件时,二进制表示可以避开大部分涉及的复杂性。

一些鼓舞人心的例子:

  • 读取映射到内存的CSV文件的最简单方法
  • 使用boost::iostreams:mapped_file_source和std::multimap
  • 使用boost对mmaped gzip文件进行迭代

您基本上发现的是,文本文件不是随机访问的,压缩使索引本质上是模糊的(从压缩流偏移到未压缩流偏移没有精确的映射)。

看看zlib发行版中的zran.c示例,如zlib FAQ:中所述

28.我可以在压缩流中随机访问数据吗

不,不是没有准备。如果在压缩时定期使用Z_FULL_FLUSH,小心地在这些点写入所有挂起的数据,并保留这些位置的索引,则可以在这些点开始解压缩。您必须小心不要经常使用Z_FULL_FLUSH,因为它会显著降低压缩性能。或者,您可以扫描deflate流一次以生成索引,然后使用该索引进行随机访问。参见examples/zran.c

您可以专门研究并行实现,例如pbzip2或pigz;这些必须使用这些"块"或"帧"来调度跨核心的负载