C++ 从 std::cout 或 std::ofstream(file) 获取 std::ostream
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/366955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Obtain a std::ostream either from std::cout or std::ofstream(file)
提问by mavam
how do I bind a std::ostream
to either std::cout
or to an std::ofstream
object, depending on a certain program condition? Although this invalid for many reasons, I would like to achieve something that is semantically equivalent to the following:
根据特定的程序条件,如何将 a 绑定std::ostream
到任std::cout
一std::ofstream
对象或对象?尽管由于多种原因这无效,但我想实现在语义上等同于以下内容的内容:
std::ostream out = condition ? &std::cout : std::ofstream(filename);
I've seen some examples that are not exception-safe, such as one from http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html:
我见过一些不是异常安全的示例,例如来自http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html 的示例:
int main(int argc, char *argv[])
{
std::ostream* fp; //1
if (argc > 1)
fp = new std::ofstream(argv[1]); //2
else
fp = &std::cout //3
*fp << "Hello world!" << std::endl; //4
if (fp!=&std::cout)
delete fp;
}
Does anyone know a better, exception-safe solution?
有谁知道更好的、异常安全的解决方案?
回答by Johannes Schaub - litb
std::streambuf * buf;
std::ofstream of;
if(!condition) {
of.open("file.txt");
buf = of.rdbuf();
} else {
buf = std::cout.rdbuf();
}
std::ostream out(buf);
That associates the underlying streambuf of either cout or the output file stream to out. After that you can write to "out" and it will end up in the right destination. If you just want that everything going to std::cout
goes into a file, you can aswell do
这将 cout 或输出文件流的底层流缓冲与 out 相关联。之后,您可以写入“out”,它最终会到达正确的目的地。如果您只想将所有内容std::cout
都放入文件中,您也可以这样做
std::ofstream file("file.txt");
std::streambuf * old = std::cout.rdbuf(file.rdbuf());
// do here output to std::cout
std::cout.rdbuf(old); // restore
This second method has the drawback that it's not exception safe. You possibly want to write a class that does this using RAII:
第二种方法的缺点是它不是异常安全的。您可能想编写一个使用 RAII 执行此操作的类:
struct opiped {
opiped(std::streambuf * buf, std::ostream & os)
:os(os), old_buf(os.rdbuf(buf)) { }
~opiped() { os.rdbuf(old_buf); }
std::ostream& os;
std::streambuf * old_buf;
};
int main() {
// or: std::filebuf of;
// of.open("file.txt", std::ios_base::out);
std::ofstream of("file.txt");
{
// or: opiped raii(&of, std::cout);
opiped raii(of.rdbuf(), std::cout);
std::cout << "going into file" << std::endl;
}
std::cout << "going on screen" << std::endl;
}
Now, whatever happens, std::cout is in clean state.
现在,无论发生什么, std::cout 都处于干净状态。
回答by Tom
This is exception-safe:
这是异常安全的:
void process(std::ostream &os);
int main(int argc, char *argv[]) {
std::ostream* fp = &cout;
std::ofstream fout;
if (argc > 1) {
fout.open(argv[1]);
fp = &fout;
}
process(*fp);
}
Edit: Herb Sutter has addressed this in the article Switching Streams (Guru of the Week).
编辑:Herb Sutter 在文章Switching Streams (Guru of the Week) 中已经解决了这个问题。
回答by Tony Clifton
std::ofstream of;
std::ostream& out = condition ? std::cout : of.open(filename);
回答by user32849
Being a novice to C++, I don't know if this is exception-safe, but here's how I usually do it:
作为 C++ 的新手,我不知道这是否是异常安全的,但我通常这样做:
std::ostream& output = (condition)?*(new std::ofstream(filename)):std::cout;
回答by levir chianca
The following simple code works for me:
以下简单代码对我有用:
int main(int argc, char const *argv[]){
std::ofstream outF;
if (argc > 1)
{
outF = std::ofstream(argv[1], std::ofstream::out);
}
std::ostream& os = (argc > 1)? outF : std::cout;
}