Pipe console.writeLine() messages to a text file

2019-07-23 13:54发布

问题:

I wonder what the best approach is in implementing a logger which essentially eats all Console.WriteLine() messages and spits out a text file of all these messages.

I know I could use a StringBuilder and populate it with all the messages by doing .AppendLine wherever Console.WriteLine occurs...but I am looking for something more magical than that. Some way using which I don't have to write as many lines of code as Console.WriteLines in existing code.

And in case you missed the tags, this is for a C#4.0 console application.

回答1:

I assume what you want is a stream that writes to standard out and to a file. That is, you want everything to still show up on the console, but you also want it to be written to a file. (If you just wanted to redirect output to a file, you could do that from the command line.)

You need to create your own TextWriter-derived class, and have it do the actual output. You call Console.SetOut to make the console write to your TextWriter.

class ConsoleLogger: TextWriter
{
    private TextWriter ConsoleOutputStream;
    private StreamWriter LogOutputStream;
    public ConsoleLogger(string logFilename)
    {
        ConsoleOutputStream = Console.Out;
        // Initialize your log file
        LogOutputStream = new StreamWriter(logFilename);
    }

    public void Write(string s)
    {
        ConsoleOutputStream.Write(s);
        LogOutputStream.Write(s);
    }

    // Other Write functions format their arguments and call Write(string).
}

And in the program that uses this:

private ConsoleLogger MyLogger;
const string LogFilename = "ConsoleLog.txt";
void Main()
{
    MyLogger = new ConsoleLogger(LogFilename);
    Console.SetOut(MyLogger);
}

You don't have to override all the TextWriter methods. As the documentation says, "A derived class must minimally implement the TextWriter.Write(Char) method to make a useful instance of TextWriter."

I've done something similar to this, and it works quite well.



回答2:

Instead of using Console.Write in your code, use Trace.Write. Then in the config file, append the ConsoleTraceListener to the trace listeners.

This technique will allow you to trace, and the trace framework will output it both to the console and whatever trace listener you set up (probably TextWriterTraceListener in your case).

Some 3rd party lib (log4not goes into my mind) allows an encapsulation of all logging mechanisms too.