出力 - c# コンソール 文字 化け



コンソール出力をファイルにミラーリングする (9)

C#コンソールアプリケーションでは、コンソール出力をテキストファイルにミラーリングするスマートな方法はありますか?

現在、私は、 Console.WriteLineInstanceOfStreamWriter.WriteLine両方に同じ文字列を渡すだけです。


Arulによって提案されているように、 Console.SetOutを使用して出力をテキストファイルにリダイレクトすることができます:

Console.SetOut(new StreamWriter("Output.txt"));

StreamWriterから継承したクラスを使用するかどうかの決定は、Keep Thinkingというユーザーによる提案が機能します。 しかし、私はコンストラクタbase.AutoFlush = trueに追加する必要がありました:

{
    this.console = console;
    base.AutoFlush = true;
}

デストラクタへの明示的な呼び出し:

public new void Dispose ()
{
    base.Dispose ();
}

それ以外の場合、ファイルはすべてのデータを記録したよりも早く閉じられます。

私はそれを次のように使用しています:

CombinedWriter cw = new CombinedWriter ( "out.txt", true, Encoding.Unicode, 512, Console.Out );
Console.SetOut (cw);

log4netはこれを行うことができます。 あなたはこのようなものを書くだけです:

logger.info("Message");

構成によって、プリントアウトがコンソール、ファイル、またはその両方に行われるかどうかが決まります。


log4netチェックしてlog4net 。 log4netを使用すると、単一のログステートメントで両方の場所にログメッセージを出力できるコンソールとファイルアペンダを設定できます。


これは、ファイルとコンソールの両方への入力のリダイレクトを可能にするTextWriterをサブクラス化する単純なクラスです。

このように使用する

  using (var cc = new ConsoleCopy("mylogfile.txt"))
  {
    Console.WriteLine("testing 1-2-3");
    Console.WriteLine("testing 4-5-6");
    Console.ReadKey();
  }

ここにクラスがあります:

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;
    }
  }

}

これはもっと仕事のいくつかの種類かもしれませんが、私は反対に行くだろう。

コンソール用のTraceListenerとログファイル用のTraceListenerをインスタンス化します。 その後、 Console.Write代わりにコードでTrace.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.");
}

私が思い出す限り、アプリケーション構成でリスナーを定義して、ビルドに触れることなくロギングを有効または無効にすることができます。


優れたソリューションをお考えください。 私はいくつかのコンソール書き込みイベントをログに記録することを避けるため、いくつかのオーバーライドを追加しました。

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();
        }
    }
}

実際には、TextWriterから継承し、WriteLineメソッドをオーバーライドする独自のクラスを実装することで、Console.OutからTraceの透過ミラーリングを作成できます。

WriteLineでは、ファイルに書き込むように設定できるTraceに書き込むことができます。

この回答は非常に参考になりましたhttps://.com/a/10918320/379132 : https://.com/a/10918320/379132

それは実際に私のために働いた!


私はここから多くを学んだので、ここで私のソリューションを共有する必要があります。

最初に、StreamWriterに固有の新しいクラスを作成する必要があります。たとえばCombinedWriterです。

その後、Console.OutでCombinedWriterの新しいインスタントを初期化します。

最後に、コンソール出力をConsole.SetOutによって新しいクラスの瞬間にリダイレクトすることができます。

次のコードは私にとって新しいクラスです。

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 Write(string value)
    {
        console.Write(value);
        base.Write(value);
    }
}




console