在管道上进行读取/写入,以C语言完成文件复制 [英] Read/writing on a pipe, accomplishing file copying in C

查看:556
本文介绍了在管道上进行读取/写入,以C语言完成文件复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从文件中读取文件,然后将其写入管道,并在子进程中从管道中读取文件并将其写入新文件.该程序传递两个参数:输入文件的名称和要复制到的文件的名称.这是一个家庭作业项目,但是我花了数小时上网,并且发现了使它更加混乱的唯一方法.我们给了两个分配,这和线程的矩阵乘法.我得到的矩阵乘法没有问题,但是这一步应该很容易,我遇到了很多麻烦.我得到了要复制的文件的第一个单词,但随后出现了一大堆乱码.

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;
}

我的读写错误吗?

推荐答案

我的读写错误吗?

是的

在子级中,您正在将面向字符串的缓冲I/O(fgets())与面向块的二进制I/O混合在一起. (即write().)两种方法都可以,但是选择其中一种是正常的做法.

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.

在父级中,您仅发送单行而没有循环.之后,在fclose()缓冲的I/O系统之前,请关闭基础文件描述符.这意味着当fclose尝试刷新缓冲区时,现在关闭的描述符将无法写入任何剩余数据.

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.

您可以使用Posix指定的内核级操作write()/read()/close(),也可以使用ISO C指定的标准I的fdopen/puts/gets/fclose /O库操作.现在,有一种混合它们的方法将起作用.如果在父级中使用stdio,则仍可以在子级中使用读/写,但是随后您将对每一行进行内核调用,这通常不是理想的做法.

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.

这篇关于在管道上进行读取/写入,以C语言完成文件复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆