C ++:如何更改stdout的默认目标?

时间:2011-03-18 14:58:39

标签: c++

我有一个库,可以将内容输出到控制台。

如何更改stdout以使其写入文件而不是控制台?

4 个答案:

答案 0 :(得分:4)

尝试以下方法:

// Let fs be your file stream …
cout.rdbuf(fs.rdbuf());

重新设置internal stream buffer

答案 1 :(得分:1)

你可以只在close(1)然后dup2 stdout(1)上的任何文件描述符。

答案 2 :(得分:0)

退一步,看起来你可能遇到了图书馆设计问题。

在许多图书馆中,您应该谨慎地编写用户未告诉您编写的任何地方。这意味着您根本不应该写入标准输出,当然也不会重定向它。不要忘记,程序的其他部分可能依赖于仍然作为标准输出的标准输出,而不是写入您的库想要给我们的文件。如果有必要在某处写入,则用户应该告诉您写入的位置,或者只需打开文件并让库写入该文件,而不是标准输出。如果出现错误,库可能可以写入标准错误,但即使这样你也应该谨慎。

显然,这里的冗余语句有例外(只需指向标准I / O库)。但是,为了方便库,您正在讨论从库中重定向标准输出的事实意味着设计是可疑的。

答案 3 :(得分:0)

您可以使用此课程:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string>

class StdCapture
{
public:
    StdCapture(): m_capturing(false), m_init(false), m_oldStdOut(0), m_oldStdErr(0)
    {
        m_pipe[READ] = 0;
        m_pipe[WRITE] = 0;
        if (_pipe(m_pipe, 65536, O_BINARY) == -1)
            return;
        m_oldStdOut = dup(fileno(stdout));
        m_oldStdErr = dup(fileno(stderr));
        if (m_oldStdOut == -1 || m_oldStdErr == -1)
            return;

        m_init = true;
    }

    ~StdCapture()
    {
        if (m_capturing)
        {
            EndCapture();
        }
        if (m_oldStdOut > 0)
            close(m_oldStdOut);
        if (m_oldStdErr > 0)
            close(m_oldStdErr);
        if (m_pipe[READ] > 0)
            close(m_pipe[READ]);
        if (m_pipe[WRITE] > 0)
            close(m_pipe[WRITE]);
    }


    void BeginCapture()
    {
        if (!m_init)
            return;
        if (m_capturing)
            EndCapture();
        fflush(stdout);
        fflush(stderr);
        dup2(m_pipe[WRITE], fileno(stdout));
        dup2(m_pipe[WRITE], fileno(stderr));
        m_capturing = true;
    }

    bool EndCapture()
    {
        if (!m_init)
            return false;
        if (!m_capturing)
            return false;
        fflush(stdout);
        fflush(stderr);
        dup2(m_oldStdOut, fileno(stdout));
        dup2(m_oldStdErr, fileno(stderr));
        m_captured.clear();

        std::string buf;
        const int bufSize = 1024;
        buf.resize(bufSize);
        int bytesRead = 0;
        if (!eof(m_pipe[READ]))
        {
            bytesRead = read(m_pipe[READ], &(*buf.begin()), bufSize);
        }
        while(bytesRead == bufSize)
        {
            m_captured += buf;
            bytesRead = 0;
            if (!eof(m_pipe[READ]))
            {
                bytesRead = read(m_pipe[READ], &(*buf.begin()), bufSize);
            }
        }
        if (bytesRead > 0)
        {
            buf.resize(bytesRead);
            m_captured += buf;
        }
        return true;
    }

    std::string GetCapture() const
    {
        std::string::size_type idx = m_captured.find_last_not_of("\r\n");
        if (idx == std::string::npos)
        {
            return m_captured;
        }
        else
        {
            return m_captured.substr(0, idx+1);
        }
    }

private:
    enum PIPES { READ, WRITE };
    int m_pipe[2];
    int m_oldStdOut;
    int m_oldStdErr;
    bool m_capturing;
    bool m_init;
    std::string m_captured;
};

当您需要开始捕获时请致电BeginCapture() 当您需要停止捕获时请致电EndCapture() 调用GetCapture()来检索捕获的输出