为什么 fgets 不能从 popen 流中获取所有字节

Why fgets cannot get all bytes from a popen stream

我编译了以下代码 运行:

$ ./run_curl 'http://ftp.gnu.org/gnu/grep/grep-2.4.tar.gz'.

但是我无法获取要下载的文件的完整字节。为什么?

我使用 curl --silent 'http://ftp.gnu.org/gnu/grep/grep-2.4.tar.gz' > a.tgz 会得到完整的字节。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 512

void download_pkg(const char* url)
{
    char content[SIZE] = {0};
    FILE *fp = NULL;
    char cmd[255] = {0};
    FILE *fp_download = fopen("a.tgz", "w");
    sprintf(cmd, "curl --silent '%s'", url);
    fp = popen(cmd, "r");
    while(fgets(content, SIZE - 1, fp) != NULL) {
        fputs(content, fp_download);
    }
    fclose(fp_download);
    pclose(fp);
    return;
}

int main(int argc, char *argv[])
{
    download_pkg(argv[1]);
    return 0;
}

编辑:

根据 Jonathan Leffler 的 ,问题通过以下代码解决:

int size_read = 0;
while((size_read = fread(content, sizeof(char), SIZE - 1, fp)) > 0) {
    fwrite(content, sizeof(char), size_read, fp_download);
}

gzipped tar 文件将包含大量空字节。这些空字节将搞砸通过 fgets() 读取的数据的处理。您将错过空字节和它们之后的任何其他字节。 fgets() 不会告诉您它读取了多少字节,因此您无法安全地读取空字节。

您很可能需要使用 fread()fwrite()。至少,那些不会被数据中嵌入的空值混淆。