日常编写小工具时,使用Console.Write
会把日志输出到控制台中,这便于在运行过程查看日志,但如果日志过多,或者希望能对日志进行查找,复制操作时,在控制台中就不方便操作了,这时就希望能把日志输出到log文件中,通过Console.SetOut
可以将输出重定向到文件,不过这样就不方便在运行时查看日志进度。有没有办法可以把日志同步输出到控制台和log文件中呢?
参考StackOverflow的一个回答,其实原理很简单,就是我们自己实现一个TextWriter
,它接收一个文件和原Console的输出流,然后将输出重定向到这个TextWriter
,就可以了。
代码如下:
public class ConsoleCopy : IDisposable
{
private FileStream m_FileStream;
private StreamWriter m_FileWriter;
private readonly TextWriter m_DoubleWriter;
private readonly TextWriter m_OldOut;
private class DoubleWriter : TextWriter
{
private TextWriter m_One;
private TextWriter m_Two;
public DoubleWriter(TextWriter one, TextWriter two)
{
m_One = one;
m_Two = two;
}
public override Encoding Encoding
{
get { return m_One.Encoding; }
}
public override void Flush()
{
m_One.Flush();
m_Two.Flush();
}
public override void Write(char value)
{
m_One.Write(value);
m_Two.Write(value);
}
}
public ConsoleCopy(string path)
{
m_OldOut = Console.Out;
try {
m_FileStream = File.Create(path);
m_FileWriter = new StreamWriter(m_FileStream)
{
AutoFlush = true
};
m_DoubleWriter = new DoubleWriter(m_FileWriter, m_OldOut);
}
catch (Exception e) {
Console.WriteLine("Cannot open file for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(m_DoubleWriter);
}
public void Dispose()
{
Console.SetOut(m_OldOut);
if (m_FileWriter != null) {
m_FileWriter.Flush();
m_FileWriter.Close();
m_FileWriter = null;
}
if (m_FileStream != null) {
m_FileStream.Close();
m_FileStream = null;
}
}
}
使用方法如下:
using (var cc = new ConsoleCopy("mylogfile.txt"))
{
Console.WriteLine("testing 1-2-3");
Console.WriteLine("testing 4-5-6");
Console.ReadKey();
}
这个方法最大的好处就是不用修改原有的Console.Write
,只要在程序入口处将主逻辑用using包住,内部所有的输出都能同步输出到控制台和log文件了。