繁体   English   中英

如何使用C中的管道将信息输出到文件?

[英]How to output to a file with information from a pipe in C?

我对执行完第二个程序后尝试输出到文件时的错误感到困惑。

说我有以下名称的输入文件:

马蒂·B·海滩7 8
扎卡里湾 惠特克12 23
伊万·桑切斯02 15
吉姆·塔冈加纳9 03

我的程序完成后,它将把学生的姓名转换为他们的用户名,并将其输出到这样的文件中:

mbb0708
zbw1223
is0215
jt0903

目前,按照我的程序的立场,它什么也不输出到文件,并且终端似乎陷入了无限循环,尽管之前对我的转换器程序进行了自我测试,并确保将其正确输出到stdout。

我不确定我在做什么错吗? 第一次使用管道编程。 我知道必须利用读取和写入命令来提取数据,但是使用dup2命令是仅读取命令所必需的吗?

经理

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(int argc, char** argv)
{
    pid_t pid;

    int nbytes;

    /*Buffer to hold data from pipe*/
    char buffer[BUFSIZ + 1];

    /*Pipe Information*/
    int commpipe[2];
    if(pipe(commpipe))
    {
        fprintf(stderr, "Pipe failed.\n");
        return EXIT_FAILURE;
    }

    if((pid = fork()) == -1)
    {
        fprintf(stderr,"Fork error. Exiting.\n"); 
        exit(1);
    }
    else if(pid == 0)
    {
        /*This is the child process. Close our copy of the write end of the file descriptor.*/
        close(commpipe[1]);
        /* Connect the read end of the pipe to standard input*/
        dup2(commpipe[0], STDIN_FILENO);
        /*Program will convert the Student's name to their respective names*/
        execl("converter","converter",NULL);
        /*Exit if failure appears*/
        exit(EXIT_FAILURE);
    }
    else
    {
        FILE *file;
        file = fopen("usernames.txt","a+"); //append a file(add text to a file or create a file it does not exist)
        /*Close or copy of the read end of the file descriptor */
        //close(commpipe[1]);

        nbytes = write(commpipe[1], buffer, BUFSIZ);

        //Read from pipe here first? 

        //Output to usernames.txt the usernames of the user from the pipe.
        fprintf(file, "%s", buffer);

        /*Wait for the child process to finish*/
        waitpid(pid, NULL, 0);
    }

    return 0;
}

一个问题是,管理器将所有数据发送到转换器后,管理器没有关闭commpipe[1] 因此,转换器将永远不会在stdin上获得EOF,因此不会退出。

经理极有可能由于缓冲而没有从转换器获取任何数据。 当不写入终端时,stdio的某些实现使用全缓冲区缓冲(与行缓冲相反)。 一旦解决了先前的错误并关闭了该进程,将刷新stdout。 您还可以考虑在puts行之后添加fflush(stdout)

看一下OpenGroup网站,有一个与您相似的示例。 我建议您首先使用一些硬编码的示例。 一旦工作,添加代码以读取和写入结果。

我做了一些小的改动以使示例正常工作:

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

int main(int argc, char** argv){
   int fildes[2];
   const int BSIZE = 100;
   char buf[BSIZE];
   ssize_t nbytes;
   int status;


   status = pipe(fildes);
   if (status == -1 ) {
       /* an error occurred */
       printf("Error!\n");
       exit(-1);
   }

   printf("Forking!\n");
   switch (fork()) {
   case -1: /* Handle error */
       printf("Broken Handle :(\n");
       break;


   case 0:  /* Child - reads from pipe */
       printf("Child!\n");
       close(fildes[1]);                       /* Write end is unused */
       nbytes = read(fildes[0], buf, BSIZE);   /* Get data from pipe */
       /* At this point, a further read would see end of file ... */
       assert(nbytes < BSIZE);                 /* Prevent buffer overflow */
       buf[nbytes] = '\0';                     /* buf won't be NUL terminated */
       printf("Child received %s", buf);
       close(fildes[0]);                       /* Finished with pipe */
       fflush(stdout);
       exit(EXIT_SUCCESS);


   default:  /* Parent - writes to pipe */
       printf("Parent!\n");
       close(fildes[0]);                       /* Read end is unused */
       write(fildes[1], "Hello world\n", 12);  /* Write data on pipe */
       close(fildes[1]);                       /* Child will see EOF */
       /* Note that the Parent should wait for a response from the
       child here, because the child process will be terminated once
       the parent exits */
       exit(EXIT_SUCCESS);
   }

   return 0;
}

据我了解,您的转换器程序从stdin读取行并将其写入stdout。 由于管道是单向实体,因此您需要两个管道与管理器进行通信-一个管道将数据发送到转换器,另一个管道从转换器接收输出。

也许您应该考虑增强转换器以采用(作为可选参数)输入和输出文件的名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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