Warm tip: This article is reproduced from serverfault.com, please click

how to loop through File stream

发布于 2020-11-30 01:09:12

I would like to know if there is a way I can loop through a FILE *ptr so that I can get its size.For example:

char *buffer = malloc(512);
FILE *command = popen("pwd","r");
pclose(command);

I would like to loop through *command output until the end and create a counter size++ that way I can calculate its size. But I don't know how to do the loop here. If anyone could please tell me if this is possible and how. Thanks.

Questioner
PedroVLP
Viewed
12
William Pursell 2020-11-30 17:05:04

You can only read data from the pipe once. If you want to calculate the amount of data, you will need to store it all and count. Something like:

#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

static void * xrealloc(void *buf, size_t num, size_t siz, void *end);
struct string{ char *start, *end; size_t cap; };

static void
push(int c, struct string *b)
{
        if( b->start == NULL || b->end >= b->start + b->cap ) {
                b->start = xrealloc(b->start, b->cap += 128,
                        sizeof *b->start, &b->end);
        }
        *b->end++ = c;
}

int
main(int argc, char **argv)
{
        int c;
        int text = 1;
        char *cmd = argc > 1 ? argv[1] : "pwd";
        struct string content = {0};
        FILE *command = popen(cmd,"r");
        if( command == NULL ) {
                perror("pwd");
                return EXIT_FAILURE;
        }
        while( (c = getc(command)) != EOF ){
                push(c, &content);
                if( ! isprint(c) && ! isspace(c)) {
                        text = 0;
                }
        }
        printf("%zu bytes\n", content.end - content.start);
        if( text ) {
                push('\0', &content);
                printf("%s", content.start);
        }
        return 0;
}
static void *
xrealloc(void *buf, size_t num, size_t siz, void *endvp)
{
        void **endp = endvp;
        ptrdiff_t offset = endp && *endp ? *endp - buf : 0;
        buf = realloc(buf, num * siz);
        if( buf == NULL ){
                perror("realloc");
                exit(EXIT_FAILURE);
        }
        if( endp != NULL ){
                *endp = buf + offset;
        }
        return buf;
}