简体   繁体   English

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

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

I'm confused about what I'm doing wrong when I'm attempting to output to a file after I've execed a second program. 我对执行完第二个程序后尝试输出到文件时的错误感到困惑。

Say I have input file that has the following names: 说我有以下名称的输入文件:

Marty B. Beach 7 8 马蒂·B·海滩7 8
zachary b. 扎卡里湾 Whitaker 12 23 惠特克12 23
Ivan sanchez 02 15 伊万·桑切斯02 15
Jim Toolonganame 9 03 吉姆·塔冈加纳9 03

After my programs finish, it will convert the student's names to their usernames and output it to a file such as this: 我的程序完成后,它将把学生的姓名转换为他们的用户名,并将其输出到这样的文件中:

mbb0708 mbb0708
zbw1223 zbw1223
is0215 is0215
jt0903 jt0903

Currently as my program stands, it outputs nothing to the file and the terminal seems to be in an infinite loop despite self testing my converter program before and making sure it outputs names correctly to stdout. 目前,按照我的程序的立场,它什么也不输出到文件,并且终端似乎陷入了无限循环,尽管之前对我的转换器程序进行了自我测试,并确保将其正确输出到stdout。

I'm not sure what I'm doing wrong here? 我不确定我在做什么错吗? First time programming with pipes. 第一次使用管道编程。 I know have to make use of the read and write commands extract the data, but with the dup2 command is that necessary for the read command alone? 我知道必须利用读取和写入命令来提取数据,但是使用dup2命令是仅读取命令所必需的吗?

manager.c 经理

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

One problem is that after manager has sent all the data to converter, the manager is not closing commpipe[1] . 一个问题是,管理器将所有数据发送到转换器后,管理器没有关闭commpipe[1] Because of that, converter will never get EOF on stdin so will not exit. 因此,转换器将永远不会在stdin上获得EOF,因此不会退出。

Most likely manager isn't getting any data back from converter due to buffering. 经理极有可能由于缓冲而没有从转换器获取任何数据。 Some implementations of stdio use full-buffer buffering (as opposed to line-buffering) when not writing to a terminal. 当不写入终端时,stdio的某些实现使用全缓冲区缓冲(与行缓冲相反)。 Once you fix the previous error and get the process to close, that will flush stdout. 一旦解决了先前的错误并关闭了该进程,将刷新stdout。 You can also consider adding fflush(stdout) after your puts line. 您还可以考虑在puts行之后添加fflush(stdout)

Have a look at the OpenGroup site, there's an example that looks similar to yours. 看一下OpenGroup网站,有一个与您相似的示例。 I suggest you get the sample working first with some hard coded. 我建议您首先使用一些硬编码的示例。 Once that is working, add the code to read and write the results. 一旦工作,添加代码以读取和写入结果。

I made some minor changes to get the example working: 我做了一些小的改动以使示例正常工作:

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

As I understand, your converter program reads lines from stdin and writes them to stdout. 据我了解,您的转换器程序从stdin读取行并将其写入stdout。 As a pipe is a uni-directional entity, you will need TWO of them to communicate with the manager - one to send data to the converter and one to receive output from it. 由于管道是单向实体,因此您需要两个管道与管理器进行通信-一个管道将数据发送到转换器,另一个管道从转换器接收输出。

Maybe you should consider enhancing the converter to take (as optional arguments) the name of an input and output file. 也许您应该考虑增强转换器以采用(作为可选参数)输入和输出文件的名称。

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

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