将数据从多个流重定向到单个流,同时保留原始数据
Redirect data from multiple streams to a single stream while keeping original data
简而言之,我正在尝试创建一个链接到文件 std::ofstream outFile{pathToFile, std::ios_base::app};
的流。该文件是一个日志文件,理想情况下,它会接收 stderr 和 stdout 的副本。当发生错误时,例如,错误将打印在文件中的控制台和中。
我试过使用 freopen(pathToFile, "a+", stderr);
和 std::cerr.rdbuf(outFile.rdbuf());
,但是,这两个都完全重定向输出,类似于 bash 中的管道。我也想在控制台中查看错误。
作为 C++ 流的新手,我不太确定如何实现这一点。我认为用另一种语言完成它的方式是“订阅”stderr,因此每次 stderr 更改并更新自身时,我的原始流都会收到通知。另一种方法是覆盖 stderr,登录到我的文件并调用原始文件,但由于程序员本身通常不调用 stderr,我不确定我该怎么做。
请注意,我使用的是 windows,因此我无法访问 unistd.h
。我还想避免使用 STL
或第三方库。
IOStreams 在内部使用 std::streambuf
来实际写入(或读取)字符。如果你只是想重定向所有写入另一个流的字符,你可以只重定向相应的流缓冲区。不过,您最终应该恢复原始流缓冲区,因为流在销毁时会被刷新,并且流缓冲区的生命周期很重要。例如
#include <iostream>
#include <fstream>
struct redirect {
std::ostream& d_stream;
std::streambuf* d_orig;
redirect(std::ostream& out, std::ostream& to)
: d_stream(out)
, d_orig(out.rdbuf(to.rdbuf())) {
}
~redirect() { this->d_stream.rdbuf(this->d_orig); }
};
int main() {
std::ofstream log("my-log.txt");
redirect rcout(std::cout, log);
redirect rcerr(std::cerr, log);
std::cout << "hello, ";
std::cerr << "world!\n";
}
如果您也想要重定向的流出现在原始流上,您可以使用“teestream
”,它使用流缓冲区将每个字符复制到两个不同的流缓冲区(我过去曾在多个地方发布过此类流的多个版本,包括 Whosebug)。
简而言之,我正在尝试创建一个链接到文件 std::ofstream outFile{pathToFile, std::ios_base::app};
的流。该文件是一个日志文件,理想情况下,它会接收 stderr 和 stdout 的副本。当发生错误时,例如,错误将打印在文件中的控制台和中。
我试过使用 freopen(pathToFile, "a+", stderr);
和 std::cerr.rdbuf(outFile.rdbuf());
,但是,这两个都完全重定向输出,类似于 bash 中的管道。我也想在控制台中查看错误。
作为 C++ 流的新手,我不太确定如何实现这一点。我认为用另一种语言完成它的方式是“订阅”stderr,因此每次 stderr 更改并更新自身时,我的原始流都会收到通知。另一种方法是覆盖 stderr,登录到我的文件并调用原始文件,但由于程序员本身通常不调用 stderr,我不确定我该怎么做。
请注意,我使用的是 windows,因此我无法访问 unistd.h
。我还想避免使用 STL
或第三方库。
IOStreams 在内部使用 std::streambuf
来实际写入(或读取)字符。如果你只是想重定向所有写入另一个流的字符,你可以只重定向相应的流缓冲区。不过,您最终应该恢复原始流缓冲区,因为流在销毁时会被刷新,并且流缓冲区的生命周期很重要。例如
#include <iostream>
#include <fstream>
struct redirect {
std::ostream& d_stream;
std::streambuf* d_orig;
redirect(std::ostream& out, std::ostream& to)
: d_stream(out)
, d_orig(out.rdbuf(to.rdbuf())) {
}
~redirect() { this->d_stream.rdbuf(this->d_orig); }
};
int main() {
std::ofstream log("my-log.txt");
redirect rcout(std::cout, log);
redirect rcerr(std::cerr, log);
std::cout << "hello, ";
std::cerr << "world!\n";
}
如果您也想要重定向的流出现在原始流上,您可以使用“teestream
”,它使用流缓冲区将每个字符复制到两个不同的流缓冲区(我过去曾在多个地方发布过此类流的多个版本,包括 Whosebug)。