c++ - 如何将 boost::iostreams::mapped_file_source 与 gzip 压缩的输入文件一起使用

标签 c++ boost gzip memory-mapped-files

我正在使用 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)。你能告诉我如何在第二个代码中设置这两个值吗?

最佳答案

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


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

如果您的实际文件存储空间不小,那么您应该考虑二进制表示,或者保持文本原样。

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

一些鼓舞人心的例子:


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

查看 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 use Z_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. See examples/zran.c

¹ 您可以具体查看并行实现,例如pbzip2 或 pigz;这些将必然使用这些“ block ”或“帧”来跨内核调度负载

关于c++ - 如何将 boost::iostreams::mapped_file_source 与 gzip 压缩的输入文件一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29574044/

相关文章:

c++ - IEEE float 和 double 是否保证在任何操作系统上都具有相同的大小?

c++ - 如何在不区分大小写的情况下检查文本文件是否为回文

c++ - 用于 Web 开发的高效 C++ 软件堆栈

c++ - Boost::带有共享指针的侵入式列表

c++ - 包含 BGL : call to strong_components fails to compile when random_spanning_tree. hpp

c++11 - C++11 是否有像 Boost 的scoped_array 这样的动态分配数组的包装器?

java - gzip 压缩不适用于我的自定义 java HTTP 服务器

c++ - 访问继承函数

java - 使用 GZIP、JSON 响应和 JQuery

css - React 生产在桌面和移动设备的 css 文件之间困惑