c++ - 从 std::cout 或 std::ofstream(file) 获取 std::ostream

标签 c++ exception-handling iostream

如何将 std::ostream 绑定(bind)到 std::coutstd::ofstream 对象,具体取决于某个程序条件?尽管由于多种原因这无效,但我想实现在语义上等同于以下内容的东西:

std::ostream out = condition ? &std::cout : std::ofstream(filename);

我见过一些不是异常安全的例子,比如来自 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;
}

有谁知道更好的、异常安全的解决方案?

最佳答案

std::streambuf * buf;
std::ofstream of;

if(!condition) {
    of.open("file.txt");
    buf = of.rdbuf();
} else {
    buf = std::cout.rdbuf();
}

std::ostream out(buf);

这将 cout 或输出文件流的底层 streambuf 关联到 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

第二种方法的缺点是它不是异常安全的。您可能想编写一个使用 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;
}

现在,无论发生什么,std::cout 都处于干净状态。

关于c++ - 从 std::cout 或 std::ofstream(file) 获取 std::ostream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/366955/

相关文章:

c++ - 如何从无法直接访问的地方将消息/事件推送到消息队列中?

java - 我想从抛出Java程序的当前异常中提取一个字符串

c++ - C++ 中的多重定义错误,即使我没有包含多个文件

c++ - 从 std::vector<unsigned char> 读取二进制数据的最简单方法?

ios - 取消请求的错误处理

c++ - 对 `std::istreambuf_iterator` 的用法感到困惑

c++ - 跨平台浮点一致性

java - Java 与 C++ 中的一元运算符

C++ sax2解析器问题

scala - 使用 Akka actors 进行异常处理