在c ++中处理大型gzfile

问题描述 投票:1回答:2
char buffer[1001];
for(;!gzeof(m_fHandle);){ 
         gzread(m_fHandle, buffer, 1000);
     The file I'm handling is more than 1GB.

将整个文件加载到缓冲区?或者我应该malloc并分配大小?

或者我应该逐行加载它?该文件有一个“\ n”标记EOL。如果是这样,我该怎么做才能在c ++中处理gzfile?

c++ file gz
2个回答
2
投票

zlib的方法是:

您可以反复调用缓冲区大小有限的gzread。如果你可以确定他的最大线长度是例如BUFLEN:看它Live On Coliru

#include <zlib.h>
#include <iostream>
#include <algorithm>

static const unsigned BUFLEN = 1024;

void error(const char* const msg)
{
    std::cerr << msg << "\n";
    exit(255);
}

void process(gzFile in)
{
    char buf[BUFLEN];
    char* offset = buf;

    for (;;) {
        int err, len = sizeof(buf)-(offset-buf);
        if (len == 0) error("Buffer to small for input line lengths");

        len = gzread(in, offset, len);

        if (len == 0) break;    
        if (len <  0) error(gzerror(in, &err));

        char* cur = buf;
        char* end = offset+len;

        for (char* eol; (cur<end) && (eol = std::find(cur, end, '\n')) < end; cur = eol + 1)
        {
            std::cout << std::string(cur, eol) << "\n";
        }

        // any trailing data in [eol, end) now is a partial line
        offset = std::copy(cur, end, buf);
    }

    // BIG CATCH: don't forget about trailing data without eol :)
    std::cout << std::string(buf, offset);

    if (gzclose(in) != Z_OK) error("failed gzclose");
}

int main()
{
    process(gzopen("test.gz", "rb"));
}

如果你不知道最大线的大小,我建议抽象它多一点,并从std::basic_streambuf推导underflow,所以你可以使用std::getline与基于此缓冲区的istream

更新由于您是C ++的新手,实现自己的streambuf可能不是一个好主意。我建议使用c ++库(而不是zlib)。

例如。 Boost Iostream允许您简单地执行此操作:

Live On Coliru

#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>    

namespace io = boost::iostreams;

int main()
{   
    io::filtering_istream in;
    in.push(io::gzip_decompressor());
    in.push(io::file_source("my_file.txt"));
    // read from in using std::istream interface

    std::string line;
    while (std::getline(in, line, '\n'))
    {
         process(line); // your code :)
    }
}


0
投票

你说这是一个gzfile。这意味着二进制格式,其中'\ n'对EOL无效(没有二进制文件的EOL概念。)

也就是说,实际上你有两种缓冲区大小的选择。将整个文件加载到内存中对于您作为开发人员处理数据肯定会更容易。但是,就任务所消耗的内存而言,这是一种代价高昂的解决方案。

如果内存是一个问题,那么你需要处理数据。可能一次尝试获取最佳数据量,其中很大一部分取决于从CPU到缓存线,内存总线,SATA总线,甚至是CPU的机器的硬件架构。保存文件本身的驱动器。

如果这只是你正在解决的问题,并且你在现代计算机上运行它,那么1GB可能可以保留在内存中。只需新增一个uint8_t []文件的大小并读取整个内容然后解析数据。

否则,您需要将文件的解析与文件的读取集成在一起。

© www.soinside.com 2019 - 2024. All rights reserved.