Bir C # konsol uygulamasında, konsol çıktısının bir metin dosyasına yansıtılmasını sağlamanın akıllı bir yolu var mı?
Şu anda aynı dizeyi her ikisine Console.WriteLine
ve InstanceOfStreamWriter.WriteLine
bir günlük yöntemine geçiriyorum.
Yanıtlar:
Bu bir tür daha iş olabilir, ama ben tam tersi olurum.
Bir örneğini TraceListener
günlük dosyası için konsolu ve biri için; daha sonra Trace.Write
kodunuzda yerine ifadeler kullanın Console.Write
. Daha sonra günlüğü veya konsol çıktısını kaldırmak veya başka bir günlük kaydı mekanizması eklemek daha kolay hale gelir.
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.");
}
Hatırlayabildiğim kadarıyla, uygulama yapılandırmasında dinleyicileri tanımlayarak, yapıya dokunmadan günlüğe kaydetmeyi etkinleştirebilir veya devre dışı bırakabilirsiniz.
Bu, girdinin hem bir dosyaya hem de konsola yeniden yönlendirilmesine izin vermek için TextWriter'ın alt sınıflarını oluşturan basit bir sınıftır.
Bunu böyle kullan
using (var cc = new ConsoleCopy("mylogfile.txt"))
{
Console.WriteLine("testing 1-2-3");
Console.WriteLine("testing 4-5-6");
Console.ReadKey();
}
İşte sınıf:
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;
}
}
}
Console.WriteLine()
, tam olarak istediğim buydu.
Console.SetOut(doubleWriter);
. Konsol için globalde değişiklik yapmak biraz zaman aldı, çünkü pratikte hiçbir şeyin global olmadığı uygulamalarda çalışmaya çok alıştım. İyi şeyler!
Log4net'e göz atın . Log4net ile tek bir günlük ifadesiyle her iki yere de günlük mesajları gönderebilecek konsol ve dosya ekleyicileri kurabilirsiniz.
>
Komutu kullanarak çıktıyı bir dosyaya yönlendiremez misiniz ?
c:\>Console.exe > c:/temp/output.txt
Yansıtmanız gerekirse tee
, çıktıyı bir dosyaya bölen bir win32 sürümünü bulmayı deneyebilirsiniz .
PowerShell'den tee çalıştırmak için /superuser/74127/tee-for-windows adresine bakın
TextWriter sınıfını alt sınıflara ayırabilir ve daha sonra örneğini Console.Out'a Console.SetOut yöntemini kullanarak atayabilirsiniz - bu, özellikle aynı dizeyi günlük yönteminde her iki yönteme de iletmekle aynı şeyi yapar.
Başka bir yol, kendi Console sınıfınızı bildirebilir ve sınıfları ayırt etmek için using ifadesini kullanabilir:
using Console = My.Very.Own.Little.Console;
Standart konsola erişmek için şunlara ihtiyacınız vardır:
global::Console.Whatever
DÜZENLEME: Bu yöntem, üçüncü taraf paketinden gelen konsol bilgilerinin yeniden yönlendirilmesine olanak sağlar. WriteLine yöntemini geçersiz kılmak benim durumum için iyidir, ancak üçüncü taraf paketine bağlı olarak diğer Yazma yöntemlerini geçersiz kılmanız gerekebilir.
İlk olarak StreamWriter'dan doğal olarak yeni bir sınıf oluşturmamız gerekiyor, örneğin CombinedWriter;
Ardından Console.Out ile yeni bir CombinedWriter hazırlayın;
Son olarak, Console.SetOut ile konsol çıktısını yeni sınıfın anına yönlendirebiliriz;
Aşağıdaki kod yeni sınıf benim için çalışıyor.
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);
}
}
public override void Write(char value);
, public override void Write(char[] buffer);
, public override void Write(string value);
ve public override void Write(char[] buffer, int index, int count);
. Aksi takdirde, WriteLine(format, ...)
yöntemi kullanırsanız konsola yazdırmaz .
Log4net bunu sizin için yapabilir. Sadece şöyle bir şey yazarsın:
logger.info("Message");
Yapılandırma, çıktının konsola mı, dosyaya mı yoksa her ikisine birden mi gideceğini belirleyecektir.
Bence zaten kullanmakta olduğunuz şey en iyi yaklaşım. Çıktınızı esasen yansıtmak için basit bir yöntem.
İlk önce başlangıçta global bir TextWriter bildirin:
private TextWriter txtMirror = new StreamWriter("mirror.txt");
Ardından yazmak için bir yöntem yapın:
// Write empty line
private void Log()
{
Console.WriteLine();
txtMirror.WriteLine();
}
// Write text
private void Log(string strText)
{
Console.WriteLine(strText);
txtMirror.WriteLine(strText);
}
Şimdi kullanmak yerine Console.WriteLine("...");
kullanın Log("...");
. Bu kadar basit. Daha da kısa!
İmleç pozisyonunu ( Console.SetCursorPosition(x, y);
) kaydırırsanız bazı sorunlar olabilir , ancak aksi takdirde iyi çalışır, ben de kullanırım!
Tabii ki, Console.Write();
sadece WriteLines kullanmıyorsanız, aynı şekilde bir yöntem oluşturabilirsiniz .
StreamWriter'dan miras alınan bir sınıfı kullanma kararı, kullanıcının önerileri Keep Thinking, işe yarar. Ama yapıcı tabanına eklemem gerekiyordu.AutoFlush = true:
{
this.console = console;
base.AutoFlush = true;
}
ve yıkıcıya açık bir çağrı:
public new void Dispose ()
{
base.Dispose ();
}
Aksi takdirde, dosya tüm verileri kaydettiğinden daha önce kapatılır.
Bunu şu şekilde kullanıyorum:
CombinedWriter cw = new CombinedWriter ( "out.txt", true, Encoding.Unicode, 512, Console.Out );
Console.SetOut (cw);
Mükemmel çözüm için Düşünmeye Devam Et'e teşekkür ederiz! Yalnızca konsol ekranı için beklenen (amaçlarım için) belirli konsol yazma olaylarını günlüğe kaydetmekten kaçınmak için bazı geçersiz kılmalar ekledim.
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();
}
}
}
Kontrol etmediğiniz bir koddan, örneğin üçüncü taraf kitaplıktan konsol çıktısını çoğaltırsanız, tüm TextWriter üyelerinin üzerine yazılmalıdır. Kod, bu başlıktaki fikirleri kullanır.
Kullanım:
using (StreamWriter writer = new StreamWriter(filePath))
{
using (new ConsoleMirroring(writer))
{
// code using console output
}
}
ConsoleMirroring sınıfı
public class ConsoleMirroring : TextWriter
{
private TextWriter _consoleOutput;
private TextWriter _consoleError;
private StreamWriter _streamWriter;
public ConsoleMirroring(StreamWriter streamWriter)
{
this._streamWriter = streamWriter;
_consoleOutput = Console.Out;
_consoleError = Console.Error;
Console.SetOut(this);
Console.SetError(this);
}
public override Encoding Encoding { get { return _consoleOutput.Encoding; } }
public override IFormatProvider FormatProvider { get { return _consoleOutput.FormatProvider; } }
public override string NewLine { get { return _consoleOutput.NewLine; } set { _consoleOutput.NewLine = value; } }
public override void Close()
{
_consoleOutput.Close();
_streamWriter.Close();
}
public override void Flush()
{
_consoleOutput.Flush();
_streamWriter.Flush();
}
public override void Write(double value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(string value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(object value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(decimal value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(float value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(bool value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(int value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(uint value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(ulong value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(long value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(char[] buffer)
{
_consoleOutput.Write(buffer);
_streamWriter.Write(buffer);
}
public override void Write(char value)
{
_consoleOutput.Write(value);
_streamWriter.Write(value);
}
public override void Write(string format, params object[] arg)
{
_consoleOutput.Write(format, arg);
_streamWriter.Write(format, arg);
}
public override void Write(string format, object arg0)
{
_consoleOutput.Write(format, arg0);
_streamWriter.Write(format, arg0);
}
public override void Write(string format, object arg0, object arg1)
{
_consoleOutput.Write(format, arg0, arg1);
_streamWriter.Write(format, arg0, arg1);
}
public override void Write(char[] buffer, int index, int count)
{
_consoleOutput.Write(buffer, index, count);
_streamWriter.Write(buffer, index, count);
}
public override void Write(string format, object arg0, object arg1, object arg2)
{
_consoleOutput.Write(format, arg0, arg1, arg2);
_streamWriter.Write(format, arg0, arg1, arg2);
}
public override void WriteLine()
{
_consoleOutput.WriteLine();
_streamWriter.WriteLine();
}
public override void WriteLine(double value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(decimal value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(string value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(object value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(float value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(bool value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(uint value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(long value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(ulong value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(int value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(char[] buffer)
{
_consoleOutput.WriteLine(buffer);
_streamWriter.WriteLine(buffer);
}
public override void WriteLine(char value)
{
_consoleOutput.WriteLine(value);
_streamWriter.WriteLine(value);
}
public override void WriteLine(string format, params object[] arg)
{
_consoleOutput.WriteLine(format, arg);
_streamWriter.WriteLine(format, arg);
}
public override void WriteLine(string format, object arg0)
{
_consoleOutput.WriteLine(format, arg0);
_streamWriter.WriteLine(format, arg0);
}
public override void WriteLine(string format, object arg0, object arg1)
{
_consoleOutput.WriteLine(format, arg0, arg1);
_streamWriter.WriteLine(format, arg0, arg1);
}
public override void WriteLine(char[] buffer, int index, int count)
{
_consoleOutput.WriteLine(buffer, index, count);
_streamWriter.WriteLine(buffer, index, count);
}
public override void WriteLine(string format, object arg0, object arg1, object arg2)
{
_consoleOutput.WriteLine(format, arg0, arg1, arg2);
_streamWriter.WriteLine(format, arg0, arg1, arg2);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Console.SetOut(_consoleOutput);
Console.SetError(_consoleError);
}
}
}
TextWriter'dan miras alınan kendi sınıfınızı uygulayarak ve WriteLine yöntemini geçersiz kılarak, Console.Out to Trace'in şeffaf bir yansımasını gerçekten oluşturabilirsiniz.
WriteLine'da bunu Trace'e yazabilir ve daha sonra dosyaya yazacak şekilde yapılandırılabilir.
Bu yanıtı çok yararlı buldum: https://stackoverflow.com/a/10918320/379132
Aslında benim için çalıştı!
Cevabım en çok oy alan kabul edilmeyen cevaba ve aynı zamanda şimdiye kadarki en zarif çözüm olduğunu düşündüğüm en az oy alan cevaba dayanıyor . Kullanabileceğiniz akış türü açısından biraz daha geneldir ( MemoryStream
örneğin bir kullanabilirsiniz ), ancak kısalık için ikinci yanıtta bulunan tüm genişletilmiş işlevleri atladım.
class ConsoleMirrorWriter : TextWriter
{
private readonly StreamWriter _writer;
private readonly TextWriter _consoleOut;
public ConsoleMirrorWriter(Stream stream)
{
_writer = new StreamWriter(stream);
_consoleOut = Console.Out;
Console.SetOut(this);
}
public override Encoding Encoding => _writer.Encoding;
public override void Flush()
{
_writer.Flush();
_consoleOut.Flush();
}
public override void Write(char value)
{
_writer.Write(value);
_consoleOut.Write(value);
}
protected override void Dispose(bool disposing)
{
if (!disposing) return;
_writer.Dispose();
Console.SetOut(_consoleOut);
}
}
Kullanım:
using (var stream = File.Create(Path.Combine(Path.GetTempPath(), AppDomain.CurrentDomain.FriendlyName)))
using (var writer = new ConsoleMirrorWriter(stream))
{
// Code using console output.
}