.NETではConsoleクラスのメソッドを使うことで自プロセスの標準入力(standard input, stdin
)や標準出力(standard output, stdout
)などの標準ストリーム(standard streams)に対する入出力操作を行うことができるようになっています。
Console.WriteLine等のメソッドで標準出力への書き込み、Console.ReadLine等のメソッドで標準入力からの読み込みが行えます。 また、Console.In/Console.Outプロパティを参照することで標準入出力をTextReader/Textwriterとして参照することもできます。 標準エラー(standard error, stderr
)への出力にはConsole.Errorプロパティを使用します。
ファイルに対する入出力を行うStream派生クラスとしてFileStreamクラスが存在しますが、.NETには標準ストリームに直接対応するStream派生クラスは公開されていません(StandardStreamのようなクラスは存在しない)。 そのかわりに、Console.OpenStandardOutputなどのメソッドを使って標準ストリームに対応するStreamを取得できるため、ファイルと同様に標準ストリームを扱うこともできるようになっています。 このほか、標準ストリームをリダイレクトして、標準ストリームの入出力先をFileStreamやMemoryStreamなどに変更することもできます。
ここでは、Consoleクラスを使って自プロセスの標準ストリームを操作する方法について解説します。 子プロセスを起動して、そのプロセスの標準ストリームを操作する方法については子プロセスの標準入出力にて解説しています。
標準ストリームに対する読み込み・書き込み
標準ストリームに対する読み込み・書き込みは、Consoleクラスに用意されている静的メソッドを呼び出すことで行うことができます。
標準出力への書き込み
ConsoleクラスのメソッドWrite, WriteLineなどを使うことで標準出力への書き込みを行うことができます。 標準出力の実際の出力先はコンソールウィンドウ、リダイレクトされたファイルやIDEの出力ペインなどとなり、アプリケーションの種類や実行環境によって変わります。
Write, WriteLineメソッドでは書式を指定した書き込みもできるようになっています。
書式を指定した書き込みについては書式指定子で解説しています。
標準入力からの読み込み
ReadLineメソッドを使うことで標準入力から1行分の文字列を読み込むことができます。 ReadLineメソッドの戻り値には改行文字は含まれないため、末尾の改行文字を取り除くchomp
/chop
のような操作は不要です。
コマンドプロンプトで実行した場合(標準入力がターミナルに接続されている場合)は、ReadLineメソッドはエンターキーが押されるまで待機します。 標準入力がパイプ等に接続されている場合は、その接続先から1行分読み込んだ時点で処理が戻ります。 なお、ReadLineメソッドではCR/LF/CRLFのいずれかを改行として扱います。
またReadLineメソッドは、リダイレクトやパイプで渡される内容が終端(EOF)に達した場合や、コンソールアプリケーションにおいてCTRL+Z(LinuxではCTRL+D)によって入力を中断した場合など、それ以上標準入力から読み込める文字列がない場合にはnull
/Nothing
を返します。
コンソールアプリケーションではCTRL+Cを押下することでアプリケーションが中断します。 CTRL+Cが押下されたときの動作を変更したい場合は、Console.CancelKeyPressイベントにイベントハンドラを設定することで動作を定義することができます。
標準入出力との接続については§.標準ストリームのリダイレクトや子プロセスの標準入出力 §.自プロセスと子プロセスの標準ストリームをパイプする、リダイレクト・パイプなどコマンドラインでの操作についてはMS-DOSコマンドプロンプトTips §.パイプとリダイレクトを参照してください。
Readメソッドを使うと標準入力から1文字ずつ読み込むことができます。 ReadLineメソッドとは異なり、Readメソッドでは改行文字もそのまま読み込まれます。
Readメソッドは読み込んだ文字をchar/Char型の範囲の数値(int/Integer型)として返すため、文字として参照する場合は戻り値をChar型にキャストします。 標準入力から読み込める文字列がなくなった場合やCTRL+Zによって入力を中断した場合、Readメソッドは-1を返します。
ReadLine, Readメソッドではキー入力された文字はそのままコンソールウィンドウにも表示されます(エコーバックされる)。 キー入力を表示したくない場合、エコーバックしないようにしたい場合はReadKeyメソッドを使うことができます。
ReadKeyメソッドの使用例はエコーバックせずに文字列を入力する(Console.ReadKey)をご覧ください。
標準入出力のReader/Writer
Console.InプロパティやConsole.Outプロパティを使うことでも標準入出力への読み書きを行うことができます。 Console.WriteLine
とConsole.Out.WriteLine
はどちらも標準出力への書き込み、Console.ReadLine
とConsole.In.ReadLine
は標準入力からの読み込みを行います。 動作および結果はどちらも同じです。
Console.In/Outは、それぞれ標準入出力への読み書きを行うTextReader/TextWriterとなっています。 このため、標準入出力をファイル入出力などと同様に扱いたい場合などにこれらのプロパティを活用することができます。 Console.In
/Console.Out
は、JavaにおけるSystem.in
/System.out
や、Pythonにおけるsys.stdin
/sys.stdout
に相当するものと言えます。
標準エラーへの書き込みを行うTextWriterを取得するためのConsole.Errorプロパティも存在します。
標準ストリームをTextReader/Writerではなく、Streamで扱いたい場合はConsole.OpenStandardInputなどのメソッドを使用します。
Console.Inを使った一例を挙げます。 Consoleクラスには標準入力に書き込まれる内容すべてを読み込むメソッドは存在しませんが、TextReaderにはReadToEndメソッドが用意されているため、これを使って標準入力の内容すべてを読み込むことができます。
コンソールアプリケーションの場合、上記のコードはCTRL-Z(LinuxではCTRL+D)で標準入力への入力を終了しない限りReadToEndメソッドから処理が戻らず待機状態になります。
コマンドラインでのリダイレクト・パイプと標準入出力との接続についてはMS-DOSコマンドプロンプトTips §.パイプとリダイレクトを参照してください。
XmlDocumentクラスなどではTextReader/TextWriterを入力元・出力先とすることができるようになっています。 こういったクラスでは、Console.In/Console.Outを指定することで標準入出力から直接読み書きすることができるようになります。
標準エラー
Console.WriteLineやConsole.ReadLineなど、直接対応するメソッドがある標準入出力とは異なり、Consoleクラスには直接標準エラーへ書き込むためのメソッドは用意されていません。
標準エラーへの書き込みを行う場合は、Console.Errorプロパティを使って書き込みを行います。 Console.ErrorもConsole.Outと同様、標準エラーへの書き込みを行うTextWriterとなっています。
標準出力と同様、標準エラーの実際の出力先はコンソールウィンドウ、リダイレクトされたファイルやIDEの出力ペインなどとなり、アプリケーションの種類や実行環境によって変わります。
コマンドラインでのリダイレクト・パイプと標準入出力との接続についてはMS-DOSコマンドプロンプトTips §.パイプとリダイレクトを参照してください。
標準ストリームの取得
Console.In/Out/ErrorはTextReader/TextWriterであり、これはテキストデータの入出力には向いているものの、バイナリデータの入出力には不向きです。 標準ストリームでバイナリデータを扱いたい場合などにはOpenStandardInput/OpenStandardOutput/OpenStandardErrorの各メソッドを使います。
これらのメソッドではそれぞれ標準入力・標準出力・標準エラーに対応するStreamを取得することができます。 取得したStreamを使って直接読み書きをできるほか、取得したStreamからBinaryReader/BinaryWriterを作成してバイナリデータの読み書きを行うといったこともできます。
次の例では、標準入力から読み込んだ画像を水平方向に反転し、標準出力に書き込んでいます。
OpenStandardInput/OpenStandardOutput/OpenStandardErrorの各メソッドで得られる標準ストリームのStreamをラップすることにより、暗号化や圧縮・バッファリングなどの機能を付け加えることもできます。
次の例ではbase64
コマンドに似たプログラムを実装しています。 CryptoStreamを使って標準入出力のStreamをラップすることにより、標準入力から読み込んだ内容をBASE64エンコード/デコードして標準出力に書き込んでいます。
ストリームのラップについて、また暗号化や圧縮などのフォーマット変換、バッファリングなどの機能を付け加える方法等についてはストリームの基本とStreamクラス §.データフォーマットの変換やバッファリングなどの機能を追加するStream派生クラスも参照してください。
取得した標準ストリームを使う例として、コマンドラインオプションで標準入力とファイル入力を切り替える例を実装しているMD5ハッシュ文字列の作成 §.MD5クラスを使ってmd5sumコマンドを実装するもあわせてご覧ください。
標準ストリームのリダイレクト
SetIn/SetOut/SetErrorの各メソッドを使うと、実行時に標準ストリームを任意のTextReader/Writerへとリダイレクトすることができます。
標準ストリームのリダイレクトを行うと、Console.WriteLineやReadLineなどのメソッドの入出力先は、リダイレクト先として指定されたTextReader/Writerへと変更されます。
次の例ではSetOutメソッドを使って標準出力の出力先を実行時に開いたファイルに変更しています。
Console.In/Out/Errorプロパティから取得できるTextReader/Writerをリダイレクトする前に退避しておき、あとで再度リダイレクト先として設定することにより、一度リダイレクトした標準ストリームの入出力先を元の状態に戻すことができます。
TextReader/Writerクラスは抽象クラスであるため、たいていの場合リダイレクト先の設定には派生クラスであるStreamReader/Writerを使うことになります。 TextReader/WriterおよびStreamReader/Writerの作成や扱い方についてはStreamReaderクラス・StreamWriterクラスを参照してください。
SetIn/SetOut/SetErrorメソッドではStreamをリダイレクト先として直接設定することはできません。 Streamをリダイレクト先として設定したい場合は、そのStreamをベースにしてStreamReader/Writerを作成する必要があります。 具体的な方法についてはStreamReaderクラス・StreamWriterクラス §.任意のStreamからの読み込み・書き込みを参照してください。
標準出力の破棄・空の標準入力 (NUL, /dev/null)
TextReader.NullフィールドやTextWriter.Nullフィールドを標準ストリームのリダイレクト先として設定すると、標準ストリームをnullデバイス(NUL
, /dev/null
)にリダイレクトするのと同様の効果が得られます。 TextReader.Nullフィールドは空(長さ0)の標準入力として利用でき、TextWriter.Nullは空の標準出力として利用できます。
特にTextWriter.Nullは、標準出力のリダイレクト先として設定することにより、出力される内容を一切破棄する(何も出力させない)ことができます。
標準ストリームがリダイレクトされているか調べる
.NET Framework 4.5以降では、IsInputRedirected/IsOutputRedirected/IsErrorRedirectedの各プロパティを参照することにより、自プロセスの標準ストリームがリダイレクトされているかどうかを知ることができるようになっています。
これらのプロパティは、コマンドラインで標準ストリームのパイプ・リダイレクトを行った場合にtrueとなるほか、SetIn/SetOut/SetErrorメソッドによってリダイレクトを行った場合もtrueとなります。
これらのプロパティをチェックすることで標準出力の出力先がコンソールウィンドウかどうかを知ることができるため、リダイレクトされているときはConsole.ForegroundColor/BackgroundColorプロパティで文字色を変えたり、Console.CursorLeft/CursorTopプロパティでカーソルの位置を変えたりしないようにする、といったことができます。
.NET Framework 4.5より前のバージョンではこれらのプロパティは用意されないため、c# - How to detect if Console.In (stdin) has been redirected? - Stack Overflowで提示されているような方法を使って調べる必要があります。
標準ストリームのエンコーディング
InputEncoding/OutputEncodingプロパティを指定することで、標準入出力で使用されるエンコーディングを指定・変更することができます。
Consoleクラスでは、実行環境で用いられる文字コードに基づいて標準入出力のエンコーディングが設定されますが、これとは別のエンコーディングを使用する必要がある場合には、このプロパティを変更します。
このプロパティを指定することで、例えば標準入力には常にShift_JISを用い、標準出力にはUTF-8を用いる、といったことができます。
コンソールの文字コードを変更するコマンドchcp
についてはMS-DOSコマンドプロンプトTips §.文字コードの変更を参照してください。
なお、ErrorEncodingプロパティは存在しないため、標準エラーのエンコーディングを指定・変更することはできません。 SetErrorメソッドを使えば任意のTextWriterを指定できるため、目的のエンコーディングを使用するStreamWriterを作成して標準エラーのリダイレクト先として指定する、といったことはできます。
OutputEncodingプロパティにUTF-8などのエンコーディングを指定すると、標準出力にBOM(Byte Order Mark)が出力される場合があります。 この動作はランタイムの種類や実行環境によって異なります。 詳細についてはEncodingクラスとBOMありなしの制御 §.Consoleクラスを参照してください。