如何将stdout和stderr freopen()放到Windows下的单个输出文件中

时间:2018-05-15 19:17:42

标签: windows stdout stderr freopen

我有一个Windows Win32 / GUI应用程序,有时会向stdoutstderr输出有趣的输出,所以我想做的是将输出捕获到申请退出后要审核的文件。

问题是,我可以成功调用freopen_s()stdout输出捕获到文件中,我可以使用它将stderr输出捕获到文件,但尝试同时执行两个操作只会产生带有munged数据的截断文件。

下面是一个简单的程序,可以重现问题;如果我注释掉两个freopen_s()调用中的任何一个,那么我会在创建的blah.txt文件中获得预期的输出(即两个文本行中的一个),但是我所做的是什么就像最终得到包含两个文本行的blah.txt一样。

这可能在Windows下吗?我可以回过头来创建两个不同的文件(例如blah_stdout.txtblah_stderr.txt),但我不愿意,因为那时我必须手动重建stdout和stdout的相对顺序。生成了stderr输出。

int main(int argc, char *argv[])
{
   const char * outFileName = "blah.txt";
   FILE * junk1 = NULL, junk2 = NULL;
   if (freopen_s(&junk1, outFileName, "w", stdout) != 0) abort();
   if (freopen_s(&junk2, outFileName , "w", stderr) != 0) abort();
   printf("This text was printed to stdout and should appear in blah.txt\n");
   fprintf(stderr, "This text was printed to stderr and should appear in blah.txt\n");
   return 0;
}

1 个答案:

答案 0 :(得分:1)

“w”打开模式记录为

  

打开一个空文件进行写入。如果给定文件存在,则其内容将被销毁。

但即使是“w +”和“a”也会失败。

如果您使用的是具有dup2的CRT,您可以这样做:

#include <io.h> // MS CRT

...

FILE * junk1 = NULL;
if (freopen_s(&junk1, outFileName, "w", stdout) != 0) abort();
_dup2(1, 2); // Assign stderr to same file as stdout

当我测试它时,这段代码将两行写入文件,但从评论中可以明显看出这可能并非总是如此。较旧版本的Visual Studio更有可能发挥作用。

如果您愿意抛弃所有可移植性,您也可以直接访问FILE对象(struct _iobuf)后面的结构(_iob / __iob_func)并覆盖成员使用其他文件的值。这是not possible in VS 2015 and later

  

FILE封装:在以前的版本中,FILE类型在&lt; stdio.h&gt;中完全定义,因此用户代码可以通过其内部进入FILE和muck。我们重构了stdio库以改进库实现细节的封装。作为其中的一部分,定义的FILE现在是一个不透明的类型,其成员无法从CRT本身外部访问。