A method to log and display text in a console screen simultaneously. I had always had the necessity to display long text outputs on the console screen. The size of the text displayed usually exceeds the amount of text that can be accessed by scrolling up through he console output. Also, there had been times when I wanted to look at the output history, to spot out abnormalities or bugs. Doing this was difficult until I decided to write a  logger. Logging all the output text to a file, and simultaneously displaying it solves the above problems. 



Source code:

#ifndef FILELOGGER_H_
#define FILELOGGER_H_

#include &lt;fstream&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;

class FileLogger;

template &lt;class Type&gt;
FileLogger&amp; operator &lt;&lt; ( FileLogger&amp; logCout, const Type&amp; data);


class FileLogger {
    std::string fileName;
    bool __linkWithFile;
    bool __linkWithCout;
    bool __appendToFile;
public:

    FileLogger(const std::string&amp; pfileName, bool pAppendToFile = true): fileName(pfileName),
                                              __linkWithFile(true),
                                              __linkWithCout(true)
                                              {
        if (pfileName == "&lt;null&gt;") {
             __linkWithFile = false;
        }

        __appendToFile = pAppendToFile;
    }
    FileLogger(const FileLogger&amp; flog) {
        fileName       = flog.fileName;
        __linkWithFile = flog.__linkWithFile;
        __linkWithCout = flog.__linkWithCout;
        __appendToFile = flog.__appendToFile;
    }

    void linkWithCout() {
        __linkWithCout = true;
    }

    void unlinkWithCout() {
        __linkWithCout = false;
    }

    void linkWithFile() {
        __linkWithFile = true;
    }

    void unlinkWithFile() {
        __linkWithFile = false;
    }

    template &lt;class Type&gt; friend FileLogger&amp; operator &lt;&lt; ( FileLogger&amp; logCout, const Type&amp; data);


    void flush_console() {
        std::cout.flush();
    }

    ~FileLogger(){}

};


template &lt;class Type&gt;
FileLogger&amp; operator &lt;&lt; ( FileLogger&amp; logCout, const Type&amp; data) {
    if(logCout.__linkWithCout)
        std::cout &lt;&lt; data;
    if(logCout.__linkWithFile) {
        std::ofstream fout;
        fout.open(logCout.fileName.c_str(),
                                            ((logCout.__appendToFile) ?(std::ios::out | std::ios::app) :
                                                    std::ios::out) );
        logCout.__appendToFile = true;
        fout &lt;&lt; data;
    }
    return (logCout);
}

#endif


Example usage:

FileLogger logCout ("log.text", false);

// writes to both the screen and to the file `log.text`. 
logCout &lt;&lt; "Hello " &lt;&lt; "World";
// appends the next line to the file by default.
logCout &lt;&lt; "!";


 Explanation:


The functions, void linkWithCout() and void unlinkWithCout() can be used to force the class to write the output text to the screen and refrain from writing the output text to the screen respectively.
The functions, void linkWithFile() and void unlinkWithFile() can be used to force the class to write the output text to the file and refrain from writing the output text to the file respectively.


Is there a better way to achieve this functionality? Or is there any possible modifications that could help this become more useful (probably like linking this to multiple log files)?
Is it necessary?

I don't see what this achieves that can't be done by piping the output of your program through tee or similar; it just removes flexibility (you can no longer not save the logs).

Naming

All identifiers containing double underscore are reserved for the implementation for any purpose - including as macros.  So you'll need to remove those from the relevant names.

Allow moving rvalues

In the constructor, it's better to accept the file name by value, and std::move() it into the member:

FileLogger(std::string pfileName, bool appendToFile = true)
    : fileName(std::move(pfileName)),
      linkWithFile(fileName!="&lt;null&gt;"),
      linkWithCout(true),
      appendToFile(appendToFile)
{}


Omit what can be defaulted

There's no need for a copy constructor that's identical to the compiler-provided one, so just omit that - and then you won't inhibit the generation of a move constructor.

Extensibility

How about a more composable, general-purpose tee_stream class?  Then you can output to as many locations as you like, chosen on the fly at runtime.

Don't surprise your users

Given FileLogger logCout ("log.text", false);, then  logCout &lt;&lt; "Hello " &lt;&lt; "World"; opens the file, writes Hello to it, closes it, then opens it again, truncating and replacing the contents with World.  Most users would expect both Hello and World to be present after that line.

You should document somewhere that users can't write to a file called &lt;null&gt; - or change the magic name to a better value, such as the empty string (then the test becomes !fileName.empty()).