C# 将控制台输出镜像到文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/420429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mirroring console output to a file
提问by xyz
In a C# console application, is there a smart way to have console output mirrored to a text file?
在 C# 控制台应用程序中,是否有一种智能方法可以将控制台输出镜像到文本文件?
Currently I am just passing the same string to both Console.WriteLine
and InstanceOfStreamWriter.WriteLine
in a log method.
目前,我只是路过相同的字符串既Console.WriteLine
和InstanceOfStreamWriter.WriteLine
在日志方法。
采纳答案by Oliver Friedrich
This may be some kind of more work, but I would go the other way round.
这可能需要更多的工作,但我会反其道而行之。
Instantiate a TraceListener
for the console and one for the log file; thereafter use Trace.Write
statements in your code instead of Console.Write
. It becomes easier afterwards to remove the log, or the console output, or to attach another logging mechanism.
TraceListener
为控制台实例化一个,为日志文件实例化一个;此后Trace.Write
在您的代码中使用语句而不是Console.Write
. 之后删除日志或控制台输出或附加其他日志记录机制变得更容易。
static void Main(string[] args)
{
Trace.Listeners.Clear();
TextWriterTraceListener twtl = new TextWriterTraceListener(Path.Combine(Path.GetTempPath(), AppDomain.CurrentDomain.FriendlyName));
twtl.Name = "TextLogger";
twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime;
ConsoleTraceListener ctl = new ConsoleTraceListener(false);
ctl.TraceOutputOptions = TraceOptions.DateTime;
Trace.Listeners.Add(twtl);
Trace.Listeners.Add(ctl);
Trace.AutoFlush = true;
Trace.WriteLine("The first line to be in the logfile and on the console.");
}
As far as I can recall, you can define the listeners in the application configuration making it possible to activate or deactivate the logging without touching the build.
据我所知,您可以在应用程序配置中定义侦听器,从而可以在不接触构建的情况下激活或停用日志记录。
回答by tvanfosson
回答by kgiannakakis
回答by arul
You could subclass the TextWriter class, and then assign its instance to the Console.Out using the Console.SetOutmethod - which in particular does the same thing as passing the same string to both methods in the log method.
您可以子类化 TextWriter 类,然后使用Console.SetOut方法将其实例分配给Console.Out- 特别是将相同的字符串传递给 log 方法中的两个方法。
Another way might declaring your own Console class and use the using statement to distinguish between the classes:
另一种方法可能是声明您自己的 Console 类并使用 using 语句来区分这些类:
using Console = My.Very.Own.Little.Console;
To access the standard console you'd then need:
要访问标准控制台,您需要:
global::Console.Whatever
回答by xtofl
Can't you just redirect the output to a file, using the >
command?
您不能使用>
命令将输出重定向到文件吗?
c:\>Console.exe > c:/temp/output.txt
If you need to mirror, you can try find a win32 version of tee
that splits the output to a file.
如果您需要镜像,您可以尝试找到tee
将输出拆分为文件的 win32 版本。
See https://superuser.com/questions/74127/tee-for-windowsto run teefrom PowerShell
请参阅https://superuser.com/questions/74127/tee-for-windows以从 PowerShell运行tee
回答by Christian
This is a simple class which subclasses TextWriter to allow redirection of the input to both a file and the console.
这是一个简单的类,它继承了 TextWriter 以允许将输入重定向到文件和控制台。
Use it like this
像这样使用它
using (var cc = new ConsoleCopy("mylogfile.txt"))
{
Console.WriteLine("testing 1-2-3");
Console.WriteLine("testing 4-5-6");
Console.ReadKey();
}
Here is the class:
这是课程:
class ConsoleCopy : IDisposable
{
FileStream fileStream;
StreamWriter fileWriter;
TextWriter doubleWriter;
TextWriter oldOut;
class DoubleWriter : TextWriter
{
TextWriter one;
TextWriter two;
public DoubleWriter(TextWriter one, TextWriter two)
{
this.one = one;
this.two = two;
}
public override Encoding Encoding
{
get { return one.Encoding; }
}
public override void Flush()
{
one.Flush();
two.Flush();
}
public override void Write(char value)
{
one.Write(value);
two.Write(value);
}
}
public ConsoleCopy(string path)
{
oldOut = Console.Out;
try
{
fileStream = File.Create(path);
fileWriter = new StreamWriter(fileStream);
fileWriter.AutoFlush = true;
doubleWriter = new DoubleWriter(fileWriter, oldOut);
}
catch (Exception e)
{
Console.WriteLine("Cannot open file for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(doubleWriter);
}
public void Dispose()
{
Console.SetOut(oldOut);
if (fileWriter != null)
{
fileWriter.Flush();
fileWriter.Close();
fileWriter = null;
}
if (fileStream != null)
{
fileStream.Close();
fileStream = null;
}
}
}
回答by hgirish
As suggested by Arul, using Console.SetOut
can be used to redirect output to a text file:
正如 Arul 所建议的, usingConsole.SetOut
可用于将输出重定向到文本文件:
Console.SetOut(new StreamWriter("Output.txt"));
回答by Keep Thinking
EDIT: This method provide the possibility to redirect the console information come from third party package. override the WriteLine method is good for my situation, but you may need to override other Write methods depends on the third party package.
编辑:此方法提供了重定向来自第三方包的控制台信息的可能性。覆盖 WriteLine 方法对我的情况有好处,但是您可能需要覆盖其他 Write 方法,这取决于第三方包。
First we need to create new class inherent from StreamWriter, say CombinedWriter;
首先,我们需要创建 StreamWriter 固有的新类,比如 CombinedWriter;
Then init a new instant of CombinedWriter with Console.Out;
然后用 Console.Out 初始化一个新的 CombinedWriter 瞬间;
Finally we can redirect console output to the instant of the new class by Console.SetOut;
最后,我们可以通过 Console.SetOut 将控制台输出重定向到新类的时刻;
Following code is the new class works for me.
以下代码是对我有用的新课程。
public class CombinedWriter : StreamWriter
{
TextWriter console;
public CombinedWriter(string path, bool append, Encoding encoding, int bufferSize, TextWriter console)
:base(path, append, encoding, bufferSize)
{
this.console = console;
base.AutoFlush = true; // thanks for @konoplinovich reminding
}
public override void WriteLine(string value)
{
console.Write(value);
base.WriteLine(value);
}
}
回答by konoplinovich
The decision to use a class, inherited from the StreamWriter, suggestions by user Keep Thinking, works. But I had to to add into constructor base.AutoFlush = true:
使用继承自 StreamWriter 的类的决定,以及用户 Keep Thinking 的建议,有效。但我不得不添加到构造函数 base.AutoFlush = true 中:
{
this.console = console;
base.AutoFlush = true;
}
аnd an explicit call to the destructor:
以及对析构函数的显式调用:
public new void Dispose ()
{
base.Dispose ();
}
Otherwise, the file is closed earlier than he recorded all the data.
否则,文件在他记录所有数据之前关闭。
I am using it as:
我将它用作:
CombinedWriter cw = new CombinedWriter ( "out.txt", true, Encoding.Unicode, 512, Console.Out );
Console.SetOut (cw);
回答by user2789183
Thank you to Keep Thinking for the excellent solution! I added some further overrides to avoid logging certain console write events that (for my purposes) are only expected for console display.
感谢 Keep Thinking 提供出色的解决方案!我添加了一些进一步的覆盖,以避免记录某些控制台写入事件(出于我的目的)仅用于控制台显示。
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RedirectOutput
{
public class CombinedWriter : StreamWriter
{
TextWriter console;
public CombinedWriter(string path, bool append, TextWriter consoleout)
: base(path, append)
{
this.console = consoleout;
base.AutoFlush = true;
}
public override void Write(string value)
{
console.Write(value);
//base.Write(value);//do not log writes without line ends as these are only for console display
}
public override void WriteLine()
{
console.WriteLine();
//base.WriteLine();//do not log empty writes as these are only for advancing console display
}
public override void WriteLine(string value)
{
console.WriteLine(value);
if (value != "")
{
base.WriteLine(value);
}
}
public new void Dispose()
{
base.Dispose();
}
}
class Program
{
static void Main(string[] args)
{
CombinedWriter cw = new CombinedWriter("combined.log", false, Console.Out);
Console.SetOut(cw);
Console.WriteLine("Line 1");
Console.WriteLine();
Console.WriteLine("Line 2");
Console.WriteLine("");
for (int i = 0; i < 10; i++)
{
Console.Write("Waiting " + i.ToString());
Console.CursorLeft = 0;
}
Console.WriteLine();
for (int i = 0; i < 10; i++)
{
Console.Write("Waiting " + i.ToString());
}
Console.WriteLine();
Console.WriteLine("Line 3");
cw.Dispose();
}
}
}