我正在编写一个类来从应用程序内部显示自定义控制台。我也使用glog
将消息记录到文件中,同时记录到stderr。如何让我的控制台类听stderr?
我想过制作一个自定义的fstream并做类似的事情:
CustomStream cs;
auto original_buf = std::cerr.rdbuf(cs.rdbuf());
并调用发送到控制台类的stream operator <<
。
或者直接从std::filebuf
继承并调用:
CustomFilebuf fb;
auto original_buf = std::cerr.rdbuf(&fb);
这是正确的方法吗?我搜索了一些示例代码,但找不到很多。
Edit1:我尝试使用流式传输,但是glog会记录stderr
而不是std::cerr
,所以我无法获取任何数据。
答案 0 :(得分:1)
我不确定这是否与您的问题相关,但是......
ISO C99在7.19.5.3第6段中说:
When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function [...], and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
也有人说从stderr读取的是“未定义的行为”...
虽然你可以从stderr读取,只要你在阅读之前刷新:
fwrite("x", 1, 1, stderr);
fflush(stderr);
fgetc(stderr);
另请查看How do I read stdout/stderr output of a child process correctly?
对于任何想要将stdout重定向到Win32应用程序中的控制台窗口的人来说 的 AllocConsole 强>
我甚至创建了一个简单的(普通的)函数来将stdout重定向到控制台窗口:
#include <fstream>
#include <io.h>
#include <fcntl.h>
#define cMaxConsoleLines 500
void ReadyConsole() {
short int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// Allocate a console for the program
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = cMaxConsoleLines; // The max number of lines for the console!
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// Redirect STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w"); // Writing to the console
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
// -------------------------------
// Redirect STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "r"); // Reading from the console
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
// ------------------------------
// Redirect STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w"); // STDERR writing to the console!
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
// ------------------------------
// Point the console to STDIO
std::ios::sync_with_stdio();
}
如果您希望控制台仅用于Debug,请确保包含<crtdbg.h>
,它定义应用程序是否处于调试模式(对于VC ++),然后,例如,您可以添加:
#ifdef _DEBUG
// The file with the ReadyConsole function
#include <DebugStuff.h>
#endif
并使用它
#ifdef _DEBUG
ReadyConsole(); // Ready the console for debugging
#endif
#ifdef _DEBUG
fprintf(stdout, "Position, Line 1, DEBUG-INFO-HERE");
cout << "COUT is working!"; // NOTE, for cout, you will need <iostream>
#endif
这是一个额外的小功能(它将消息记录到stderr 和 stderr.log文件中)
void StdErr(char* Error) {
fprintf(stderr, Error);
FILE* FP = fopen("stderr.log", "a");
fputs(Error, FP);
fclose(FP);
}