我正在尝试重定向标准输出,以便Windows应用程序中的printf可以转到我选择的文件。
我正在这样做:
outFile = fopen("log.txt", "w");
*stdout = *outFile;
setvbuf(stdout, NULL, _IONBF, 0);
但是printf仍会写入控制台(或在基于GUI的win32应用程序中无处显示)
我可以通过执行以下操作重定向“ std :: cout”:
outFileStr = std::ofstream(outFile);
std::cout.rdbuf(outFileStr.rdbuf());
但是printf似乎正在做自己的事情。 不幸的是,当我试图将python集成到C ++框架中时,我需要重定向printf,这似乎依赖于printf而不是std :: cout。
std :: cout'似乎已重定向,但不是printf。
答案 0 :(得分:5)
由于缺少在任意Win32文件句柄与高层文件描述符/流之间进行映射的适当接口,因此在Windows上重定向标准I / O的工作要多一些。
Windows上实际上有三个不同的I / O层:
printf
,scanf
等使用...)read
,write
,...使用的整数)ReadFile
,WriteFile
,...使用)要重定向C流,可以使用freopen
。例如,您可以使用以下命令重定向C stdout
:
freopen("log.txt", "w", stdout);
此重定向通常将不重定向由POSIX或Win32 API完成的I / O(如果有的话,它们仍将读/写连接的控制台)。此外,子进程不会继承此重定向。 (在兼容POSIX的/非Windows系统上,通常POSIX API也是系统API,并且C API在POSIX API之上实现。在这些情况下, 要在POSIX API级别上重定向I / O,可以使用 不幸的是,在Windows上,即使是POSIX API级别的重定向也不保证C或Win32 API级别的重定向。这是否有效取决于C库实现在POSIX文件描述符和Win32文件句柄之间进行映射所付出的努力(假定要使用的C运行时库将其I / O分层放置在POSIX之上) 。也不能保证此重定向将由产生的子代继承。 要在Windows上正确重定向I / O,您必须在最低级别(即Win32 API级别)进行重定向,并在更高级别上修复链接,如下所示: 以下是重定向 P.S。如果您可以在程序内部不进行I / O重定向,则可以使用一个小的Batch文件在命令行中简单地使用控制台的I / O重定向:freopen
就足够了。)< / p>
重定向POSIX I / O描述符
dup2
。例如,您可以重新分配文件描述符STDOUT_FILENO
来重定向stdout
,例如:int fd = open("log.txt", O_WRONLY);
dup2(fd, STDOUT_FILENO);
close(fd);
在Windows上重定向标准I / O!
CreateFile
分配新的句柄。SetStdHandle
将新的句柄分配给所需的std I / O设备。_open_osfhandle
将该新句柄与相应的C std文件描述符相关联(返回文件描述符编号)。dup2
技术重定向返回的文件描述符。stdout
的示例代码段:HANDLE new_stdout = CreateFileA("log.txt", ...);
SetStdHandle(STD_OUTPUT_HANDLE, new_stdout);
int fd = _open_osfhandle(new_stdout, O_WRONLY|O_TEXT);
dup2(fd, STDOUT_FILENO);
close(fd);
@echo off
start "my_gui_app" "path/to/my_gui_app.exe" 1> "path/to/log.txt"