我正在使用 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)。你能告诉我如何在第二个代码中设置这两个值吗?
最佳答案
答案是否定的,那是不可能的。压缩流需要有索引。
真正的问题是为什么?。您正在使用内存映射文件。进行即时压缩/解压缩只会降低性能并增加内存消耗。
如果您的实际文件存储空间不小,那么您应该考虑二进制表示,或者保持文本原样。
二进制表示可以避免使用随机访问的文本文件时涉及的大部分复杂性。
一些鼓舞人心的例子:
- Simplest way to read a CSV file mapped to memory?
- Using boost::iostreams::mapped_file_source with std::multimap
- Iterating over mmaped gzip file with boost
您基本上会发现文本文件不是随机访问的,压缩使索引基本上变得模糊(没有从压缩流偏移量到未压缩流偏移量的精确映射)。
查看 zlib FAQ 中提到的 zlib 发行版中的 zran.c
示例:
28. Can I access data randomly in a compressed stream?
No, not without some preparation. If when compressing you periodically use
Z_FULL_FLUSH
, carefully write all the pending data at those points, and keep an index of those locations, then you can start decompression at those points. You have to be careful to not useZ_FULL_FLUSH
too often, since it can significantly degrade compression. Alternatively, you can scan a deflate stream once to generate an index, and then use that index for random access. Seeexamples/zran.c
¹ 您可以具体查看并行实现,例如pbzip2 或 pigz;这些将必然使用这些“ block ”或“帧”来跨内核调度负载
关于c++ - 如何将 boost::iostreams::mapped_file_source 与 gzip 压缩的输入文件一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29574044/