为什么fgets无法从popen流中获取所有字节

时间:2015-03-14 18:32:54

标签: c popen fgets

我编译了以下代码并运行:

$ ./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的answer,问题通过以下代码解决:

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

1 个答案:

答案 0 :(得分:2)

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

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