Cracking C++(5):cout打印到文件

文章目录

    • 1. 目的
    • 2. cout 输出到控制台
    • 3. cout 输出到文件
      • 3.1 rdbuf() 函数
      • 3.2 将 cout 内容写入到文件
    • 4. 部分 cout 输出到文件, 部分 cout 输出到控制台
      • 4.1 临时切换
      • 4.2 封装为 class
    • 5. References

1. 目的

用 cout 打印到屏幕很简单, 用 ostream 打印到文件也很简单。
但, 如果一个代码中有多处 cout, 又不想一个一个改成 ostream 对象, 怎样做呢?
如果一部分 cout 希望打印到文件, 另一部分 cout 希望打印到控制台, 又该怎么做呢?

2. cout 输出到控制台

#include 
#include 
#include 
#include 

int main()
{
    using namespace std;

    cout << "hello world\n";
    cout << "学习·现代·西佳佳\n";
    cout << "__cplusplus is " << std::to_string(__cplusplus) << endl;
   
    auto givemetime = chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    cout << ctime(&givemetime) << endl;

    return 0;
}
➜  C_C++ git:(main) ✗ clang++ coutToFile.cpp -std=c++11
➜  C_C++ git:(main) ✗ ./a.out 
hello world
学习·现代·西佳佳
__cplusplus is 201103
Wed Jun  7 21:31:42 2023s

3. cout 输出到文件

关键点是, 使用 std::ostream 对象, std::ofstream 对象,以及 std::cout 的 rdbuf() 函数。

3.1 rdbuf() 函数

提供了两个函数, 互为重载版本。第一个函数不带参数, 是getter, 返回流缓冲。

std::basic_streambuf<CharT, Traits>* rdbuf() const;

Manages the associated stream buffer.
Returns the associated stream buffer. If there is no associated stream buffer, returns a null pointer.

第二个函数带参数, 是setter, 设置流缓冲。

std::basic_streambuf<CharT, Traits>* rdbuf( std::basic_streambuf<CharT, Traits>* sb );

Sets the associated stream buffer to sb. The error state is cleared by calling clear(). Returns the associated stream buffer before the operation. If there is no associated stream buffer, returns a null pointer.

3.2 将 cout 内容写入到文件

#include 
#include 
#include 
#include 
#include  // added

int main()
{
    using namespace std;

    ofstream fout("log.txt"); // added
    cout.rdbuf(fout.rdbuf()); // added

    cout << "hello world\n";
    cout << "学习·现代·西佳佳\n";
    cout << "__cplusplus is " << std::to_string(__cplusplus) << endl;
   
    auto givemetime = chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    cout << ctime(&givemetime) << endl;

    return 0;
}
➜  C_C++ git:(main) ✗ clang++ coutToFile.cpp -std=c++17
➜  C_C++ git:(main) ✗ ./a.out 
➜  C_C++ git:(main)cat log.txt 
hello world
学习·现代·西佳佳
__cplusplus is 201703
Wed Jun  7 21:36:46 2023

4. 部分 cout 输出到文件, 部分 cout 输出到控制台

也就是需要能够控制 cout 输出的位置。

4.1 临时切换

#include 
#include 
#include 
#include 
#include  // added

int main()
{
    using namespace std;

    auto stdout_buff = cout.rdbuf();
    ofstream fout("log.txt"); // added
    cout.rdbuf(fout.rdbuf()); // added

    cout << "hello world\n";
    cout << "学习·现代·西佳佳\n";
    cout.rdbuf(stdout_buff);
    cout << "__cplusplus is " << std::to_string(__cplusplus) << endl;
   
    auto givemetime = chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    cout << ctime(&givemetime) << endl;

    return 0;
}

4.2 封装为 class

使用了 RAII 的方式, 获取和恢复 src 的 stream buffer。

如果需要线程安全, 需要对 m_closed 变量加锁。

#include 
#include 
#include 
#include 
#include  // added

class Redirector
{
public:
    Redirector(std::ostream& dst, std::ostream& src) :
        m_src(src),
        m_sbuf(src.rdbuf(dst.rdbuf())),
        m_closed(false)
    {}
    ~Redirector()
    {
        if (!m_closed)
        {
            close();
        }
    }
    void close()
    {
        m_src.rdbuf(m_sbuf);
        m_closed = true;
    }

private:
    std::ostream& m_src;
    std::streambuf* const m_sbuf;
    bool m_closed;
};

int main()
{
    using namespace std;

    std::ofstream log("log2.txt");
    Redirector r(log, std::cout);

    cout << "hello world\n";
    cout << "学习·现代·西佳佳\n";
    r.close();
    
    cout << "__cplusplus is " << std::to_string(__cplusplus) << endl;
   
    auto givemetime = chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    cout << ctime(&givemetime) << endl;

    return 0;
}
➜  C_C++ git:(main) ✗ clang++ coutToFile.cpp -std=c++17
➜  C_C++ git:(main) ✗ ./a.out 
__cplusplus is 201703
Wed Jun  7 21:51:02 2023

➜  C_C++ git:(main)cat log2.txt 
hello world
学习·现代·西佳佳

5. References

  • https://stackoverflow.com/questions/52357/what-is-the-point-of-clog/56308274#56308274
  • https://en.cppreference.com/w/cpp/io/basic_ios/rdbuf

你可能感兴趣的:(C/C++,c++,开发语言)