11

C# コンソール アプリケーションで標準出力を介してユーザーにテキストを表示し、後でアクセスできるようにする方法についてアドバイスが必要です。私が実際に実装したい機能は、プログラムの実行の最後に出力バッファー全体をテキスト ファイルにダンプすることです。

よりクリーンなアプローチが見つからないときに使用する回避策はTextWriter、書き込みメソッドをオーバーライドしてサブクラス化し、ファイルへの書き込みと元の stdout ライターの両方を呼び出すことです。このようなもの:

public class DirtyWorkaround {
  private class DirtyWriter : TextWriter {
    private TextWriter stdoutWriter;
    private StreamWriter fileWriter;

    public DirtyWriter(string path, TextWriter stdoutWriter) {
      this.stdoutWriter = stdoutWriter;
      this.fileWriter = new StreamWriter(path);
    }

    override public void Write(string s) {
      stdoutWriter.Write(s);

      fileWriter.Write(s);
      fileWriter.Flush();
    }

    // Same as above for WriteLine() and WriteLine(string),
    // plus whatever methods I need to override to inherit
    // from TextWriter (Encoding.Get I guess).
  }

  public static void Main(string[] args) {
    using (DirtyWriter dw = new DirtyWriter("path", Console.Out)) {
      Console.SetOut(dw);

      // Teh codez
    }
  }
}

ファイルへの書き込みとフラッシュが常に行われていることを確認してください。実行の最後にのみ実行したいのですが、出力バッファにアクセスする方法が見つかりませんでした。

また、上記のコードの不正確さを許してください (その場しのぎに書く必要がありました。申し訳ありません;)。

4

6 に答える 6

6

これに対する完璧な解決策は、コンソール アペンダとファイル アペンダでlog4netを使用することです。他にも多くのアペンダーが利用可能です。また、実行時にさまざまなアペンダーをオフおよびオンにすることもできます。

于 2008-09-14T04:45:42.800 に答える
5

あなたのやり方に間違いはないと思います。

再利用可能なコードが必要な場合MultiWriterは、入力として 2 つ (または N?)のストリームを受け取りTextWriter、すべての書き込み、フラッシュなどをそれらのストリームに分配する or somesuch という名前のクラスを実装することを検討してください。次に、このファイル/コンソールのことを実行できますが、同様に簡単に出力ストリームを分割できます。使える!

于 2008-09-14T04:06:46.090 に答える
1

.NET 自体が使用する診断 (トレースとデバッグ) を模倣すると言えます。

テキスト出力インターフェイスに準拠するさまざまなクラスを持つことができる「出力」クラスを作成します。出力クラスにレポートすると、追加したクラス (ConsoleOutput、TextFileOutput、WhateverOutput) に指定された出力が自動的に送信されます。これにより、他の「出力」タイプ (xml/ など) を追加することもできます。適切にフォーマットされたレポートを取得するには xslt を使用しますか?)。

Trace Listeners Collectionをチェックして、私の言いたいことを確認してください。

于 2008-09-14T06:22:47.810 に答える
1

おそらくあなたが望むものではありませんが、念のため...どうやら、PowerShellは由緒あるteeコマンドのバージョンを実装しています。これはまさにこの目的のために意図されています。だから... 持っているなら吸ってください。

于 2008-09-14T04:12:43.923 に答える
0

ユーザーとの対話部分をビジネス ロジックから分離するために、アプリケーションをリファクタリングすることを検討してください。私の経験では、このような分離はプログラムの構造にとって非常に有益です。

ここで解決しようとしている特定の問題については、ユーザー操作部分の動作Console.WriteLineをファイル I/O に変更するのは簡単です。

于 2008-09-14T06:39:13.200 に答える
0

コンソールに送信された出力をキャプチャしてログに保存する同様の機能の実装に取り​​組んでいますが、出力をリアルタイムで通常のコンソールに渡しているため、アプリケーションが壊れることはありません (たとえば、コンソール アプリケーションの場合)。 !)。

コンソール出力を保存することにより、独自のコードでこれを実行しようとしている場合 (ログ システムを使用して本当に重要な情報だけを保存するのではなく)、各書き込み後のフラッシュを回避できると思います。 Flush() もオーバーライドし、stdoutWriter保存したオリジナルとfileWriter. アプリケーションが部分的な行をコンソールにフラッシュしてすぐに表示しようとしている場合 (入力プロンプト、進行状況インジケーターなど)、通常の行バッファリングをオーバーライドする場合にこれを行います。

そのアプローチでコンソール出力のバッファリングが長すぎるという問題がある場合は、WriteLine() がフラッシュされることを確認する必要があるかもしれません (ただし、Flush() オーバーライドが呼び出される場合を除いてstdoutWriter、おそらくフラッシュする必要はありません)。fileWriterしかし、元のConsole.Out(実際にはコンソールに行く)ものは改行で自動的にバッファをフラッシュすると思うので、強制する必要はありません。

Close() をオーバーライドして (フラッシュして) 閉じることもできますがfileWriter(おそらくstdoutWriter同様に)、それが本当に必要かどうか、またはベース TextWriter の Close() が Flush() を発行するかどうかはわかりません (既にオーバーライドしている)、ファイルを閉じるためにアプリケーションの終了に依存する場合があります。おそらく、終了時にフラッシュされることをテストする必要があります。また、異常終了 (クラッシュ) では、バッファリングされた出力がフラッシュされない可能性があることに注意してください。それが問題である場合、改行でフラッシュfileWriterすることが望ましいかもしれませんが、これはワームが解決する別のトリッキーな缶です。

于 2008-12-15T18:21:02.290 に答える