如何在 C 中顺序解析 gzip 压缩的文本文件而不先完全解压缩

How to sequentially parse in C a gzip-compressed text file without fully decompressing it first

我有相当大的文本文件 (~1Gb),其中包含我希望解析的顺序数据(即要读取的行,从上到下)。这些文本文件以 gzip 格式压缩。

目前,我解析这些文件的基本实现(我是 zlib 的新手,多年来没有用 C 编写过)是:

  1. 使用 zlib 库解压缩文件并将其写入磁盘 (!)
  2. 从磁盘 (!) 中读取解压后的文本文件并逐行解析

希望,一旦我了解如何更好地使用 zlib(感谢提示 ;-)),这可以得到改进:

  1. 使用 zlib 库解压缩文件并将内容保存在内存中
  2. 读取文件(从内存中)并逐行解析

不过,我认为这可以进一步优化,以便在解压缩时解析文件 "online"。我相信 gzip 解压是按顺序进行的,因此可以读取 gzip 文件,并在解压一行文本后立即将其发送到解析器?这样可以避免两次扫描文件,也可能避免将解压缩的文件保留在内存中。

这是一个 answer that says it is possible and preferable 方法。你能告诉我如何实现(或使用实现的库)这样的程序吗?

谢谢,

泰普

您可以通过 popen 打开一个 gzip 压缩文件并从流中顺序读取,就像它是未压缩的一样,除非您不能在流中搜索。

这是一些代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv) {
    char buffer[4096];
    char *cmd;
    int cmdsize;
    FILE *fp;
    int found = 0;

    if (argc < 3) {
        printf("usage: zgrep string file\n");
        return 2;
    }
    cmdsize = strlen("gunzip < ") + strlen(argv[2]) + 1;
    cmd = malloc(cmdsize);
    snprintf(cmd, cmdsize, "gunzip < %s", argv[2]);
    if ((fp = popen(cmd, "r")) == NULL) {
        perror("cannot run gunzip");
        return 1;
    }
    while (fgets(buffer, sizeof buffer, fp)) {
        if (strstr(buffer, argv[1])) {
            fputs(buffer, stdout);
            found = 1;
        }
    }
    fclose(fp);
    return found;
}

是的。您甚至不必使用 popen() 即可; zlib 包含一组函数来执行此操作:

#include <zlib.h>

gzFile fh = gzopen("file.gz", "rb");

char buf[1024];
char *line;
while ((line = gzgets(fh, buf, sizeof(buf)) != NULL) {
    // process line
}

gzclose(fh);

同样的界面还支持一行一行写入gzip文件;有关详细信息,请参阅文档。