Read/writing on a pipe, accomplishing file copying in C

╄→尐↘猪︶ㄣ 提交于 2020-01-06 07:01:53

问题


I am trying to read from a file, write it to a pipe, and in a child process read from the pipe and write it to a new file. The program is passed two parameters: the name of the input file, and the name of the file to be copied to. This is a homework project, but I have spent hours online and have found only ways of making it more confusing. We were given two assignments, this and matrix multiplication with threads. I got the matrix multiplication with no problems, but this one, which should be fairly easy, I am having so much trouble with. I get the first word of the file that I am copying, but then a whole bunch of garble.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[]) {

    if(argc < 3) {
        printf("Not enough arguments: FileCopy input.txt copy.txt\n");
        exit(0);
    }
    char buffer[200];

    pid_t pid;
    int fds[2];

    pipe(fds);
    pid = fork();


    if (pid == 0) { /* The child process */
        //wait(NULL);
        write(1, "hi i am in child\n", 17);
        int copy = open(argv[2], O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP);
        FILE* stream;
        close(fds[1]);

        stream = fdopen(fds[0], "r");
        while (fgets(buffer, sizeof(buffer), stream) != NULL) {
            //printf("%s\n", buffer);
            write(copy, buffer, 200);
            //printf("kjlkjljljlkj\n");
            //puts(buffer);

        }

        close(copy);
        close(fds[0]);

        exit(0);

    }
    else {
        write(1, "hi i am in parent\n", 18);
        FILE* input = fopen(argv[1], "r");
        FILE* stream;
        close(fds[0]);
        stream = fdopen(fds[1], "w");
        /*while (fscanf(input, "%s", buffer) != EOF) {
            //printf("%s\n", buffer);
            fprintf(stream, "%s\n", buffer);
            fflush(stream);
            //printf("howdy doody\n");
        }*/
        fgets(buffer, sizeof(buffer), input);
        printf("%s", buffer);
        fprintf(stream, "%s", buffer);
        fflush(stream);
        close(fds[1]);
        fclose(input);
        wait(NULL);
        exit(0);
    }
    return 0;
}

Am I doing the reads and writes wrong?


回答1:


Am I doing the reads and writes wrong?

Yes.

In the child, you are mixing string-oriented buffered I/O (fgets()) with block-oriented binary I/O. (That is, write().) Either approach will work, but it would be normal practice to pick one or the other.

If you mix them, you have to consider more aspects of the problem. For example, in the child, you are reading just one line from the pipe but then you write the entire buffer to the file. This is the source of the garbage characters you are probably seeing in the file.

In the parent, you are sending only a single line with no loop. And after that, you close the underlying file descriptor before you fclose() the buffered I/O system. This means when fclose tries to flush the buffer, the now-closed descriptor will not work to write any remaining data.

You can either use write()/read()/close(), which are the Posix-specified kernel-level operations, or you can use fdopen/puts/gets/fclose which are the ISO C - specified standard I/O library operations. Now, there is one way of mixing them that will work. If you use stdio in the parent, you could still use read/write in the child, but then you would be making kernel calls for each line, which would not usually be an ideal practice.




回答2:


You should generally read/write pipes only using the read/write-calls.

You should close the according ends of the pipe for child (read-only) and parent (write-only). Afterwards, write from the parent into the pipe using write()-systemcall. And in the child read using read()-systemcall.

Look here for a good explanation.



来源:https://stackoverflow.com/questions/14983451/read-writing-on-a-pipe-accomplishing-file-copying-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!