【问题标题】:writing stdin into a file with fwrite()使用 fwrite() 将标准输入写入文件
【发布时间】:2009-12-31 05:00:18
【问题描述】:

我必须在程序中捕获标准输出并将其写入文件......所以我创建了一个管道。在父进程中,我使用 dup() 捕获了管道中的标准输出,我需要将其放入文件中……所以我在子进程中执行了 dup() 以将捕获的文件描述符放入标准输入中。现在,如何使用 fwrite() 将此标准输入写入文件?

【问题讨论】:

    标签: c pipe stdin


    【解决方案1】:

    这不是很难吗?在父节点中您需要做的就是使用freopen() 将标准输出连接到您选择的文件。

    FILE *fp = freopen("/tmp/mylogfile", "w", stdout);
    
    if (fp == 0)
        error("...something went wrong opening the log file...\n");
    

    您的问题的直接答案是:

    char buffer[32768];
    ssize_t nbytes;
    FILE *fp = fopen("/tmp/mylogfile", "w");
    
    if (fp == 0)
        error("....something went wrong opening my log file...\n");
    
    while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), stdin)) > 0)
        if (fwrite(buffer, sizeof(char), nbytes, fp) != nbytes)
            error("...something went wrong writing to standard output...\n");
    

    但是,这几乎没有必要。您可以通过各种方式改进错误处理;我只是假设 'error()' 报告了一条消息并且 not 返回。

    【讨论】:

    • 是的,但这只是学习 C 的一种方式……我正在努力学习使用管道。
    • 好的 - 提到这一点并没有什么坏处;它为做事的次优技术提供了借口。我已经给出了直接的答案。但是,如果我将管道用作管道,而不是巧合地使用恰好连接到管道的文件流,我将使用文件描述符 I/O 调用(例如 read() 和 write())而不是文件流I/O 调用,例如 fread() 和 fwrite()。
    • 使用管道要记住的主要事情,尤其是在使用 dup() 时,是关闭未使用的管道末端。如果你不这样做,事情就不会正确终止。
    【解决方案2】:

    最简单的方法就是打开文件并将其作为孩子的标准输出提供:

    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    #include <stdio.h>
    
    int main() {
      pid_t pid = fork();
      switch (pid) {
      case -1:
        perror("fork");
        return 1;
    
      case 0:;
        int new_out = open("output.txt", O_WRONLY | O_CREAT, 0666);
        if (new_out == -1) {
          perror("open");
          return 1;
        }
        if (dup2(new_out, 1) == -1) {
          perror("dup2");
          return 1;
        }
        char* args[] = {"/bin/echo", "test output", 0};
        execv(args[0], args);
        perror("exec");
        return 1;
    
      default:;
        int s;
        if (waitpid(pid, &s, 0) == -1) {
          perror("waitpid");
          return 1;
        }
        if (WIFEXITED(s)) {
          return WEXITSTATUS(s);
        }
        return 1;
      }
    }
    

    【讨论】:

      【解决方案3】:

      您应该捕获到一个字节或字符缓冲区并将其发送到 fwrite。 当我说缓冲区时,我的意思是一个数组或动态分配的字节/字符块。

      【讨论】:

        猜你喜欢
        • 2012-06-01
        • 2012-06-04
        • 1970-01-01
        • 2013-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-07
        • 2011-04-09
        相关资源
        最近更新 更多