如何从压缩文件 (gz) 的字节流源中获取可读文件描述符
How to get Readable file descriptor from a byte-stream source from compressed files (gz)
我是 C 编程的新手。我使用的库需要来自字节流源的文件描述符。当我有常规文件时,它工作得很好。但是,我输入了 gz 文件的通知。我需要解析的压缩数据总量约为 5TB。我没有足够的 space 来解压它们。
我用过以下两种方法,但它们似乎不起作用,
input = gzopen (argv[i], "r");
第二种方法。
arg = argv[1];
cmd = malloc(sizeof(prefix) + strlen(arg) + 1);
if (!cmd) {
fprintf(stderr, "%s: malloc: %s\n", argv[i], strerror(errno));
return 1;
}
sprintf(cmd, "%s%s", prefix, arg);
input = popen(cmd, "r");
如果能提供任何帮助,我将不胜感激。
提前谢谢你。
我在这里进行了一些推断,因为您没有向我们展示您正在使用的库函数的原型,但是您在评论中说当文件未压缩时这对您有用:
fd = open(argv[i], O_RDONLY);
但使用 gzopen() 或 popen() 不会。所以我收集到你正在使用的库函数接受一个文件描述符参数并读取和解释数据本身。
这会导致您的直接问题 - open() returns 一个 "int" 文件描述符,但 gzopen() 和 popen() 没有。
zlib 文档以这种方式定义 gzopen():
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
所以它 returns 自定义 'gzFile' 文件描述符类型;你不能将它传递给计划执行 read() 的函数,期望一个 int 文件描述符。
同样,popen() returns 一个 stdio FILE* 文件描述符,而不是 int 类型,将它传递给需要 int 的东西也不起作用。
因此,如果您想使用 zlib,则必须使用它自己的 gzread() 函数,然后通过 int 类型描述符(可能通过管道)将您读取的数据传递给您的库函数。这会很麻烦。
您最好的选择可能是像您尝试的那样使用 popen(),但使用 stdio fileno() 函数获取作为 FILE* 基础的 int 描述符,并将其传递给您的库函数。
因此假设您原始代码中的 'prefix' 类似于 "gzip -dc ",一个将解压缩数据从您的文件流式传输到标准输出的命令,我们可以将您的代码修改为类似这样的内容(也,您为 arg 分配了值 'argv[1]' 但在其他地方使用了 'argv[i]'——我假设“1”是错字):
char *prefix, *arg, *cmd;
FILE *pinput;
int fd;
prefix = "gzip -dc ";
arg = argv[i];
cmd = malloc(strlen(prefix) + strlen(arg) + 1);
if (!cmd) {
fprintf(stderr, "%s: malloc: %s\n", argv[i], strerror(errno));
return 1;
}
sprintf(cmd, "%s%s", prefix, arg);
pinput = popen(cmd, "r");
fd = fileno(pinput);
那么您应该能够将 'fd' 传递给您的库函数并让它像处理未压缩数据一样工作。
完成后别忘了释放(cmd)!
我是 C 编程的新手。我使用的库需要来自字节流源的文件描述符。当我有常规文件时,它工作得很好。但是,我输入了 gz 文件的通知。我需要解析的压缩数据总量约为 5TB。我没有足够的 space 来解压它们。
我用过以下两种方法,但它们似乎不起作用,
input = gzopen (argv[i], "r");
第二种方法。
arg = argv[1];
cmd = malloc(sizeof(prefix) + strlen(arg) + 1);
if (!cmd) {
fprintf(stderr, "%s: malloc: %s\n", argv[i], strerror(errno));
return 1;
}
sprintf(cmd, "%s%s", prefix, arg);
input = popen(cmd, "r");
如果能提供任何帮助,我将不胜感激。
提前谢谢你。
我在这里进行了一些推断,因为您没有向我们展示您正在使用的库函数的原型,但是您在评论中说当文件未压缩时这对您有用:
fd = open(argv[i], O_RDONLY);
但使用 gzopen() 或 popen() 不会。所以我收集到你正在使用的库函数接受一个文件描述符参数并读取和解释数据本身。
这会导致您的直接问题 - open() returns 一个 "int" 文件描述符,但 gzopen() 和 popen() 没有。
zlib 文档以这种方式定义 gzopen():
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
所以它 returns 自定义 'gzFile' 文件描述符类型;你不能将它传递给计划执行 read() 的函数,期望一个 int 文件描述符。
同样,popen() returns 一个 stdio FILE* 文件描述符,而不是 int 类型,将它传递给需要 int 的东西也不起作用。
因此,如果您想使用 zlib,则必须使用它自己的 gzread() 函数,然后通过 int 类型描述符(可能通过管道)将您读取的数据传递给您的库函数。这会很麻烦。
您最好的选择可能是像您尝试的那样使用 popen(),但使用 stdio fileno() 函数获取作为 FILE* 基础的 int 描述符,并将其传递给您的库函数。
因此假设您原始代码中的 'prefix' 类似于 "gzip -dc ",一个将解压缩数据从您的文件流式传输到标准输出的命令,我们可以将您的代码修改为类似这样的内容(也,您为 arg 分配了值 'argv[1]' 但在其他地方使用了 'argv[i]'——我假设“1”是错字):
char *prefix, *arg, *cmd;
FILE *pinput;
int fd;
prefix = "gzip -dc ";
arg = argv[i];
cmd = malloc(strlen(prefix) + strlen(arg) + 1);
if (!cmd) {
fprintf(stderr, "%s: malloc: %s\n", argv[i], strerror(errno));
return 1;
}
sprintf(cmd, "%s%s", prefix, arg);
pinput = popen(cmd, "r");
fd = fileno(pinput);
那么您应该能够将 'fd' 传递给您的库函数并让它像处理未压缩数据一样工作。
完成后别忘了释放(cmd)!