将重定向的stdout和std :: ofstream同步写入unix c ++下的文件

时间:2014-04-30 12:11:04

标签: c++ unix io

这是我早期问题的一个问题:redirect stdout to a file

情况如下:我正在使用一个外部库,它为我的代码提供了重要的功能,但是它通过printf产生大量的日志信息(糟糕的风格,我知道,但我不能改变它,并且我无法切换到另一个图书馆。)

我想将输出重定向到一个文件,我已经在伟大的StackOverflow社区的帮助下实现了这一目标(参见前面的链接)。从那时起,情况变得更加复杂:现在我想将自己的日志信息附加到同一输出文件中,最好使用std :: ofstream。代码不会也永远不会被并行化,因此并发写访问不是问题。但是,请考虑以下代码:

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// this is just a global "backup" of the stdout fd
// so that I can restore it after the function call
int stdoutfd = dup(fileno(stdout));

int stupid_library_function(){
  // I can't change this function
  printf("hello world!\n");
  return 1;
}


int redirect_stdout(const char* fname, bool append){
  // redirect printf to a file
  fflush(stdout);
  int newstdout = append ? open(fname, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) : open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  dup2(newstdout, fileno(stdout));
  close(newstdout);
  return fileno(stdout);
}


int restore_stdout(){
  // restore the normal behaviour of printf
  fflush(stdout);
  dup2(stdoutfd, fileno(stdout));
  return stdoutfd;
}

int main(){
  // just to test if everything is normal
  std::cout << "this is a normal printout" << std::endl;

  // create my own output stream
  std::ofstream outstream("log.txt");

  // some of my own output
  outstream << "calling stupid library function now" << "\n";
  outstream.flush();

  // redirect the output of the supid library function to the logfile
  redirect_stdout("log.txt",true);
  int val = stupid_library_function();

  // neither of the following lines causes the output of the stupid library function to appear in the log file
  fflush(stdout);
  fsync(stdoutfd);

  // restore the normal stdout
  restore_stdout();

  // some of my own output again
  outstream << "done calling stupid library function, result was " << val << "\n";
  outstream.flush();

  // close my own output stream
  outstream.close();

  // just to test if everything is back to normal
  std::cout << "this is (again) a normal printout" << std::endl;

  return 1;

}

编译并运行此代码应该为您提供一个文件“log.txt”,其中包含以下行

calling stupid library function now
done calling stupid library function, result was 1

由于我天真的理解,该文件应包含三行,输出“hello world”来自上面找到的两个库函数调用。

我的第一个想法是刷新stdout缓冲区有问题,所以我尝试使用“fflush”和“fsync”(见上文)。但是,在这种情况下,这些似乎都没有任何效果。

有人愿意开导我并向我展示如何获得输出

calling stupid library function now
hello world
done calling stupid library function, result was 1

具有以下约束:

  • 日志文件中的行必须按正确的顺序
  • printf和std :: cout必须在代码完成后恢复为默认行为
  • 不得更改“stupid_library_function”的代码
  • “main”中的输出仍必须使用std :: ofstream

0 个答案:

没有答案