简体   繁体   中英

How to read from pipe into a file?

I would like to read from the pipe straight into a file with the code below. base_fd is a pipe.

FILE* fp = fopen("dec_data", "wb+"); 
int r_result; 
int len = msg_length-part-3;  //set to 75933
while ((r_result = read(base_fd[0], fp, len))) {
       printf("r_result: %d \n", r_result);
       len -= r_result; 
       }

The read seems to happen fine, with r_result showing 65536 and then 10397 as required. However, when I inspect the file I created, it has a size of 0 bytes...

You have a semantic error in your code. Take a look at the read(2) system call signature:

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

The second parameter to the function is a void pointer ( void *buf ), which is where read will store the count bytes it reads from fd descriptor.

However, a FILE * is an abstraction of the C library . In this answer you can see more of it. The struct FILE in MinGW32 5.1.4 is:

typedef struct _iobuf
{
    char*   _ptr;
    int _cnt;
    char*   _base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char*   _tmpfname;
} FILE;

What read will do is similar to how we copy strings. Consider this function:

void strcpy(char *dst, char *src)
{
    while(*src) *dst++ = *src++;
}

This function will copy the contents from src into dst until it finds a NULL terminating byte. This is obviously a very flawed function and should never be used, but illustrates why your example doesn't work.

Under the hood, what read is doing is very similar to this strcpy function: it is overwriting a lot of bytes in memory starting at the address pointed to by the fp pointer. You are effectively losing your reference to the FILE * pointer and the resources associated to it.

I'll bet that if you try to close(fp) after that loop you'll get a segmentation fault (it's Undefined Behavior, but I'll bet anyway).

The right way to do what you want is:

FILE* fp = fopen("dec_data", "wb+"); 
char *buf;
int r_result; 
int len = msg_length - part - 3;  //set to 75933

buf = malloc(len);
if(!buf) {
    perror("malloc");
    exit(EXIT_FAILURE);
}

while ((r_result = read(base_fd[0], buf, len))) {
    fprintf(fp, buf);
    len -= r_result; 
}

free(buf);
close(fp); // now it closes the file pointer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM