Search code examples
c++stringstreamstdstreambufostringstream

Redirecting from standard output to custom stream during program execution


I have a function which redirects messages from the standard output to a log file. The problem is, the messages are only written into the log file after the end of the program. Is it possible to write to the log file when the program is running? So, after each std::cout, a new line is added to the log file. What changes should I make?

struct Node{
        char data[100];
        struct Node* next;
    };

    class capturebuf : public std::stringbuf{
    public:
        capturebuf(){
            head = NULL;
            filename = "D:/checkouts/pointcloudbuilder/scene_plugin/log.txt";
            log.open(filename);
        }
    protected:
        struct Node* head;
        std::string filename;
        std::ofstream log;

        virtual int sync(){
                //ensure NUL termination
                overflow(0);

                struct Node* new_node = new Node();
                strcpy(new_node->data, pbase());
                new_node->next = head;
                head = new_node;

                log << head->data;

                //clear buffer
                str(std::string());
                return __super::sync();
        }
    };
    struct scoped_cout_streambuf_association{
        std::streambuf* orig;
        scoped_cout_streambuf_association( std::streambuf& buf )
            : orig(std::cout.rdbuf()){
                std::cout.rdbuf(&buf);
            }
            ~scoped_cout_streambuf_association(){
                std::cout.rdbuf(orig);
            }
    };

In the

int main() {
    capturebuf altout;
    scoped_cout_streambuf_association redirect(altout);
    return 0;
}

Solution

  • streams are buffered so you need to explicitly flush your stream with std::flush. More info in this question.

    Altering this function should help:

    virtual int sync(){
            //ensure NUL termination
            overflow(0);
    
            struct Node* new_node = new Node();
            strcpy(new_node->data, pbase());
            new_node->next = head;
            head = new_node;
    
            log << head->data << std::flush; // << add explicit flush
    
            //clear buffer
            str(std::string());
            return __super::sync();
    }