将stdout/stderr重定向到unix c ++下的文件 - 再次

car*_*ten 7 c c++ io file-descriptor io-redirection

我想做的事

将stdout和stderr重定向到c ++中的一个或多个文件

为什么我需要它

我正在使用一个外部的,预编译的第三方库,它产生了大量的输出,我想将其重定向到日志文件以保持控制台清洁.

条件

兼容性不是问题,代码只能在Unix系统上运行.重定向不仅应该影响c ++风格的打印(std :: cout <<"hello world"<< std :: endl),还应该影响c风格的打印(printf("hello world \n")).

到目前为止我尝试过的

我一直在浏览stackoverflow半天,为有类似问题的人阅读多个答案.借助这些答案,我能够将以下代码组合在一起:


#include <stdio.h>
#include <iostream>
#include <fcntl.h>
#include "unistd.h"

const int stdoutfd(dup(fileno(stdout)));

int redirect_stdout(const char* fname){
  fflush(stdout);
  int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP |     S_IROTH);
  dup2(newstdout, fileno(stdout));
  close(newstdout);
}

int restore_stdout(){
  fflush(stdout);
  dup2(stdoutfd, fileno(stdout));
  close(stdoutfd);
  return stdoutfd;
}

int main(){
  redirect_stdout("/dev/null");
  std::cout << "invisible 1" << std::endl;
  restore_stdout();
  std::cout << "visible 1" << std::endl;
  redirect_stdout("/dev/null");
  std::cout << "invisible 2" << std::endl;
  restore_stdout();
  std::cout << "visible 2" << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期望看到的内容:

visible 1
visible 2
Run Code Online (Sandbox Code Playgroud)

我实际上看到了什么

visible 1
Run Code Online (Sandbox Code Playgroud)

也就是说,当第一次使用这种机制时,它可以工作 - 但如果再次使用,恢复输出将不起作用.有人可以指出我需要改变什么才能让机制经常无限地工作吗?

Raz*_*zib 5

除了freopen()的afr0ck答案之外,我想说的是,在使用时我们应该小心。一旦像或这样的流通过分配新目标(此处为“output.txt”文件)重新打开,它总是保留在程序中,除非它已被显式更改。freopen()stdoutstdin

freopen("output.txt", "a", stdout);
Run Code Online (Sandbox Code Playgroud)

这里重新打开标准输出流stdout并分配“output.txt”文件。之后,每当我们使用-printf()或任何其他stdoutputchar()时,每个输出都会转到'output.txt'。要恢复默认行为(即在控制台/终端中打印输出),printf()我们putchar()可以使用以下代码行 -

  • 对于 gcc、linux 发行版(如 ubuntu)-freopen("/dev/tty", "w", stdout);
  • 对于 Mingw C/C++、Windows -freopen("CON", "w", stdout);

请参阅下面的代码示例 -

#include <stdio.h>

int main() {
    
    printf("No#1. This line goes to terminal/console\n");

    freopen("output.txt", "a", stdout);
    printf("No#2. This line goes to the \"output.txt\" file\n");
    printf("No#3. This line aslo goes to the \"output.txt\" file\n");

    freopen("/dev/tty", "w", stdout); /*for gcc, diffrent linux distro eg. - ubuntu*/
    //freopen("CON", "w", stdout); /*Mingw C++; Windows*/
    printf("No#4. This line again goes to terminal/console\n");        

}
Run Code Online (Sandbox Code Playgroud)

此代码会在当前目录中生成一个“output.txt”文件,并且 No#2 和 No#3 将打印在“output.txt”文件中。

谢谢


Cas*_*sey 4

如果您希望能够重用它,请不要stdoutfd关闭restore_stdout.