コンソール アプリケーションの出力を保存する方法
質問
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
}
}
}
常にファイルに書き込み、フラッシュしていることを確認します。実行の最後にのみ実行したいのですが、出力バッファにアクセスする方法が見つかりませんでした。
また、上記のコードの不正確さをお詫びします(コードを書かなければなりませんでした) このために, 、 ごめん ;)。
解決
これに対する完璧な解決策は次のとおりです。 ログフォーネット コンソール アペンダとファイル アペンダを使用します。他にも多くのアペンダーが利用可能です。また、実行時にさまざまなアペンダーをオフまたはオンにすることもできます。
他のヒント
あなたのアプローチは何も間違っていないと思います。
再利用可能なコードが必要な場合は、 というクラスの実装を検討してください。 MultiWriter
または入力として 2 (または N?) を取るようなもの TextWriter
すべての令状、フラッシュなどをストリーミングおよび配布します。それらの流れに。その後、このファイル/コンソールの処理を行うことができますが、同様に簡単に出力ストリームを分割することもできます。役に立つ!
おそらくご希望の内容ではないかもしれませんが、念のため...どうやら、 PowerShell の実装 由緒正しいバージョン tee
指示。これはまさにこの目的を意図したものです。それで...手に入れたら吸ってください。
.NET 自体が使用する診断 (トレースとデバッグ) を模倣すると思います。
テキスト出力インターフェイスに準拠するさまざまなクラスを持つことができる「出力」クラスを作成します。出力クラスにレポートすると、追加したクラス (ConsoleOutput、TextFileOutput、WhateverOutput) に指定された出力が自動的に送信されます。等々..これにより、他の「出力」タイプ (適切にフォーマットされたレポートを取得するための xml/xslt など) を追加できるようになります。
をチェックしてください トレース リスナー コレクション 私の言っている意味がわかります。
アプリケーションをリファクタリングして、ユーザー対話部分をビジネス ロジックから分離することを検討してください。私の経験では、このような分離はプログラムの構造にとって非常に有益です。
ここで解決しようとしている特定の問題については、ユーザー対話部分の動作を次のように変更することが簡単になります。 Console.WriteLine
ファイルI/Oに。
私は、アプリケーションを中断しないように、コンソールに送信された出力をキャプチャしてログに保存しながら、出力を通常のコンソールにリアルタイムで渡す同様の機能の実装に取り組んでいます。コンソール アプリケーションの場合!)。
(本当に重要な情報だけを保存するためにロギング システムを使用するのではなく) コンソール出力を保存することで独自のコードでこれを実行しようとしている場合でも、次の限り、各書き込み後のフラッシュを回避できると思います。 Flush() もオーバーライドし、元のファイルをフラッシュするようにします。 stdoutWriter
あなたもあなたのものを保存しました fileWriter
. 。これは、アプリケーションが通常の行バッファリングをオーバーライドするために、即座に表示するために部分的な行をコンソールにフラッシュしようとしている場合 (入力プロンプト、進行状況インジケーターなど) に行う必要があります。
この方法でコンソール出力のバッファリング時間が長すぎるという問題がある場合は、WriteLine() がフラッシュされることを確認する必要があるかもしれません。 stdoutWriter
(ただし、おそらく洗い流す必要はありません) fileWriter
ただし、Flush() オーバーライドが呼び出された場合を除きます)。でもオリジナルだと思うよ Console.Out
(実際にはコンソールに移動します)改行時にバッファが自動的にフラッシュされるため、強制する必要はありません。
Close() をオーバーライドして (フラッシュして) 閉じることもできます。 fileWriter
(そしておそらく stdoutWriter
も)、しかし、それが本当に必要なのか、それともベース TextWriter の Close() が Flush() (すでにオーバーライドしている) を発行し、ファイルを閉じるためにアプリケーションの終了に依存する可能性があるのかはわかりません。確実に終了時にフラッシュされるかどうかをテストする必要があります。また、異常終了 (クラッシュ) では、バッファされた出力がフラッシュされない可能性があることに注意してください。それが問題であれば、フラッシュしてください fileWriter
on newline は望ましいかもしれませんが、これも解決するのが難しいワームの缶詰です。