.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の出力ペインなどとなり、アプリケーションの種類や実行環境によって変わります。
using System;
class Sample {
static void Main()
{
Console.Write("Hello, "); // 改行なしで標準出力に書き込む
Console.WriteLine("world!"); // 改行付きで標準出力に書き込む
Console.WriteLine("Hello, world!");
}
}
Imports System
Class Sample
Shared Sub Main()
Console.Write("Hello, ") ' 改行なしで標準出力に書き込む
Console.WriteLine("world!") ' 改行付きで標準出力に書き込む
Console.WriteLine("Hello, world!")
End Sub
End Class
Hello, world! Hello, world!
Write, WriteLineメソッドでは書式を指定した書き込みもできるようになっています。
using System;
class Sample {
static void Main()
{
var intValue = 42;
var doubleValue = 3.141592654;
var dateTimeValue = new DateTime(2013, 8, 24, 1, 2, 3);
// int double, DateTimeの値をそれぞれ異なる書式で出力する
Console.WriteLine("{0:D4} {1:N3} {2:hh:ss}", intValue, doubleValue, dateTimeValue);
}
}
Imports System
Class Sample
Shared Sub Main()
Dim intValue As Integer = 42
Dim doubleValue As Double = 3.141592654
Dim dateTimeValue As New DateTime(2013, 8, 24, 1, 2, 3)
' Integer, Double, DateTimeの値をそれぞれ異なる書式で出力する
Console.WriteLine("{0:D4} {1:N3} {2:hh:ss}", intValue, doubleValue, dateTimeValue)
End Sub
End Class
0042 3.142 01:03
書式を指定した書き込みについては書式指定子で解説しています。
標準入力からの読み込み
ReadLineメソッドを使うことで標準入力から1行分の文字列を読み込むことができます。 ReadLineメソッドの戻り値には改行文字は含まれないため、末尾の改行文字を取り除くchomp
/chop
のような操作は不要です。
using System;
class Sample {
static void Main()
{
Console.WriteLine("何か入力してください");
// 標準入力から一行読み込む
var text = Console.ReadLine();
// 標準入力から読み込んだ文字列を標準出力に書き込む
Console.WriteLine("'{0}'と入力されました", text);
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine("何か入力してください")
' 標準入力から一行読み込む
Dim text = Console.ReadLine()
' 標準入力から読み込んだ文字列を標準出力に書き込む
Console.WriteLine("'{0}'と入力されました", text)
End Sub
End Class
>sample.exe
何か入力してください
Hello, world!
'Hello, world!'と入力されました
>type sample.txt Hello, line1! Hello, line2! Hello, line3! >type sample.txt | sample.exe 何か入力してください 'Hello, line1!'と入力されました
コマンドプロンプトで実行した場合(標準入力がターミナルに接続されている場合)は、ReadLineメソッドはエンターキーが押されるまで待機します。 標準入力がパイプ等に接続されている場合は、その接続先から1行分読み込んだ時点で処理が戻ります。 なお、ReadLineメソッドではCR/LF/CRLFのいずれかを改行として扱います。
またReadLineメソッドは、リダイレクトやパイプで渡される内容が終端(EOF)に達した場合や、コンソールアプリケーションにおいてCTRL+Z(LinuxではCTRL+D)によって入力を中断した場合など、それ以上標準入力から読み込める文字列がない場合にはnull
/Nothing
を返します。
using System;
class Sample {
static void Main()
{
var lineNumber = 0;
while (true) { // 無限ループ
// 標準入力から一行読み込む
var line = Console.ReadLine();
if (line == null) {
// 読み込める文字列が無くなった
break;
}
else {
// 読み込んだ文字列に行番号を付けて標準出力に書き込む
lineNumber++;
Console.WriteLine("{0}: {1}", lineNumber, line);
}
}
}
}
Imports System
Class Sample
Shared Sub Main()
Dim lineNumber As Integer = 0
While True ' 無限ループ
' 標準入力から一行読み込む
Dim line As String = Console.ReadLine()
If line Is Nothing Then
' 読み込める文字列が無くなった
Exit While
Else
' 読み込んだ文字列に行番号を付けて標準出力に書き込む
lineNumber += 1
Console.WriteLine("{0}: {1}", lineNumber, line)
End If
End While
End Sub
End Class
>sample.exe
line1
1: line1
line2
2: line2
line3
3: line3
^Z
>type sample.txt line1 line2 line3 >type sample.txt | sample.exe 1: line1 2: line2ReadメソッドはReadLineメソッドとは異なり 3: line3
コンソールアプリケーションではCTRL+Cを押下することでアプリケーションが中断します。 CTRL+Cが押下されたときの動作を変更したい場合は、Console.CancelKeyPressイベントにイベントハンドラを設定することで動作を定義することができます。
標準入出力との接続については§.標準ストリームのリダイレクトや子プロセスの標準入出力 §.自プロセスと子プロセスの標準ストリームをパイプする、リダイレクト・パイプなどコマンドラインでの操作についてはMS-DOSコマンドプロンプトTips §.パイプとリダイレクトを参照してください。
Readメソッドを使うと標準入力から1文字ずつ読み込むことができます。 ReadLineメソッドとは異なり、Readメソッドでは改行文字もそのまま読み込まれます。
Readメソッドは読み込んだ文字をchar/Char型の範囲の数値(int/Integer型)として返すため、文字として参照する場合は戻り値をChar型にキャストします。 標準入力から読み込める文字列がなくなった場合やCTRL+Zによって入力を中断した場合、Readメソッドは-1を返します。
using System;
class Sample {
static void Main()
{
while (true) { // 無限ループ
// 標準入力から一文字読み込む
int ch = Console.Read();
if (ch == -1) {
// 読み込める文字列が無くなった
break;
}
else {
// 読み込んだ文字にかっこを付けて標準出力に書き込む
var c = (char)ch;
Console.Write($"[{c}]");
}
}
}
}
Imports System
Class Sample
Shared Sub Main()
While True ' 無限ループ
' 標準入力から一文字読み込む
Dim ch As Integer = Console.Read()
If ch = -1 Then
' 読み込める文字列が無くなった
Exit While
Else
' 読み込んだ文字にかっこを付けて標準出力に書き込む
Dim c As Char = ChrW(ch)
Console.Write($"[{c}]")
End If
End While
End Sub
End Class
>sample.exe
f[f]o[o]o[o]⏎
[
]b[b]a[a]r[r]⏎
[
]
^Z
>type sample.txt foo bar >type sample.txt | sample.exe [f][o][o][ ][b][a][r][ ]
ReadLine, Readメソッドではキー入力された文字はそのままコンソールウィンドウにも表示されます(エコーバックされる)。 キー入力を表示したくない場合、エコーバックしないようにしたい場合はReadKeyメソッドを使うことができます。
ReadKeyメソッドの使用例はエコーバックせずに文字列を入力する(Console.ReadKey)をご覧ください。
標準入出力のReader/Writer
Console.InプロパティやConsole.Outプロパティを使うことでも標準入出力への読み書きを行うことができます。 Console.WriteLine
とConsole.Out.WriteLine
はどちらも標準出力への書き込み、Console.ReadLine
とConsole.In.ReadLine
は標準入力からの読み込みを行います。 動作および結果はどちらも同じです。
using System;
class Sample {
static void Main()
{
// 以下の2つはどちらも同じ動作・同じ結果となる
// Consoleクラスのメソッドを使って標準出力に書き込む
Console.WriteLine("Hello, world!");
// Console.Outプロパティを使って標準出力に書き込む
Console.Out.WriteLine("Hello, world!");
}
}
Imports System
Class Sample
Shared Sub Main()
' 以下の2つはどちらも同じ動作・同じ結果となる
' Consoleクラスのメソッドを使って標準出力に書き込む
Console.WriteLine("Hello, world!")
' Console.Outプロパティを使って標準出力に書き込む
Console.Out.WriteLine("Hello, world!")
End Sub
End Class
using System;
class Sample {
static void Main()
{
// 以下の2つはどちらも同じ動作・同じ結果となる
// Consoleクラスのメソッドを使って標準入力から読み込む
var line1 = Console.ReadLine();
// Console.Inプロパティを使って標準入力から読み込む
var line2 = Console.In.ReadLine();
}
}
Imports System
Class Sample
Shared Sub Main()
' 以下の2つはどちらも同じ動作・同じ結果となる
' Consoleクラスのメソッドを使って標準入力から読み込む
Dim line1 As String = Console.ReadLine()
' Console.Inプロパティを使って標準入力から読み込む
Dim line2 As String = Console.In.ReadLine()
End Sub
End Class
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メソッドが用意されているため、これを使って標準入力の内容すべてを読み込むことができます。
using System;
class Sample {
static void Main()
{
// ReadToEndメソッドで標準入力の内容をすべて読み込む
var text = Console.In.ReadToEnd();
// 読み込んだ内容を出力する
Console.WriteLine("(length = {0})", text.Length);
Console.WriteLine(text);
}
}
Imports System
Class Sample
Shared Sub Main()
' ReadToEndメソッドで標準入力の内容をすべて読み込む
Dim text As String = Console.In.ReadToEnd()
' 読み込んだ内容を出力する
Console.WriteLine("(length = {0})", text.Length)
Console.WriteLine(text)
End Sub
End Class
>sample.exe
line1
line2
line3
^Z
(length = 21)
line1
line2
line3
>type sample.txt line1 line2 line3 >type sample.txt | sample.exe (length = 21) line1 line2 line3
コンソールアプリケーションの場合、上記のコードはCTRL-Z(LinuxではCTRL+D)で標準入力への入力を終了しない限りReadToEndメソッドから処理が戻らず待機状態になります。
コマンドラインでのリダイレクト・パイプと標準入出力との接続についてはMS-DOSコマンドプロンプトTips §.パイプとリダイレクトを参照してください。
XmlDocumentクラスなどではTextReader/TextWriterを入力元・出力先とすることができるようになっています。 こういったクラスでは、Console.In/Console.Outを指定することで標準入出力から直接読み書きすることができるようになります。
using System;
using System.Xml;
class Sample {
static void Main()
{
var doc = new XmlDocument();
// 標準入力の内容をXMLとして読み込む
doc.Load(Console.In);
// ルート要素下に新しい要素を追加する
doc.DocumentElement.AppendChild(doc.CreateElement("bar"))
.AppendChild(doc.CreateTextNode("bar"));
// 編集したXMLを標準出力に書き込む
doc.Save(Console.Out);
}
}
Imports System
Imports System.Xml
Class Sample
Shared Sub Main()
Dim doc As New XmlDocument()
' 標準入力の内容をXMLとして読み込む
doc.Load(Console.In)
' ルート要素下に新しい要素を追加する
doc.DocumentElement.AppendChild(doc.CreateElement("bar")).AppendChild(doc.CreateTextNode("bar"))
' 編集したXMLを標準出力に書き込む
doc.Save(Console.Out)
End Sub
End Class
>type sample.xml <?xml version="1.0" ?> <doc> <foo>foo</foo> </doc> >type sample.xml | sample.exe <?xml version="1.0"?> <doc> <foo>foo</foo> <bar>bar</bar> </doc>
標準エラー
Console.WriteLineやConsole.ReadLineなど、直接対応するメソッドがある標準入出力とは異なり、Consoleクラスには直接標準エラーへ書き込むためのメソッドは用意されていません。
標準エラーへの書き込みを行う場合は、Console.Errorプロパティを使って書き込みを行います。 Console.ErrorもConsole.Outと同様、標準エラーへの書き込みを行うTextWriterとなっています。
標準出力と同様、標準エラーの実際の出力先はコンソールウィンドウ、リダイレクトされたファイルやIDEの出力ペインなどとなり、アプリケーションの種類や実行環境によって変わります。
using System;
class Sample {
static void Main()
{
// 標準出力への書き込み
Console.WriteLine("Hello, stdout!");
Console.Out.WriteLine("Hello, stdout!");
// 標準エラーへの書き込み
Console.Error.WriteLine("Hello, stderr!");
}
}
Imports System
Class Sample
Shared Sub Main()
' 標準出力への書き込み
Console.WriteLine("Hello, stdout!")
Console.Out.WriteLine("Hello, stdout!")
' 標準エラーへの書き込み
Console.Error.WriteLine("Hello, stderr!")
End Sub
End Class
>sample.exe Hello, stdout! Hello, stdout! Hello, stderr! >sample.exe > stdout.txt 2> stderr.txt >type stdout.txt Hello, stdout! Hello, stdout! >type stderr.txt Hello, stderr!
コマンドラインでのリダイレクト・パイプと標準入出力との接続についてはMS-DOSコマンドプロンプトTips §.パイプとリダイレクトを参照してください。
標準ストリームの取得
Console.In/Out/ErrorはTextReader/TextWriterであり、これはテキストデータの入出力には向いているものの、バイナリデータの入出力には不向きです。 標準ストリームでバイナリデータを扱いたい場合などにはOpenStandardInput/OpenStandardOutput/OpenStandardErrorの各メソッドを使います。
これらのメソッドではそれぞれ標準入力・標準出力・標準エラーに対応するStreamを取得することができます。 取得したStreamを使って直接読み書きをできるほか、取得したStreamからBinaryReader/BinaryWriterを作成してバイナリデータの読み書きを行うといったこともできます。
次の例では、標準入力から読み込んだ画像を水平方向に反転し、標準出力に書き込んでいます。
using System;
using System.Drawing;
using System.Drawing.Imaging;
class Sample {
static void Main()
{
// 標準入力のStreamを取得して画像として読み込む
using (var image = new Bitmap(Console.OpenStandardInput())) {
// 画像を左右反転する
image.RotateFlip(RotateFlipType.RotateNoneFlipX);
// 標準出力のStreamを取得して加工した画像を書き込む
image.Save(Console.OpenStandardOutput(), ImageFormat.Jpeg);
}
}
}
Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Class Sample
Shared Sub Main()
' 標準入力のStreamを取得して画像として読み込む
Using image As New Bitmap(Console.OpenStandardInput())
' 画像を左右反転する
image.RotateFlip(RotateFlipType.RotateNoneFlipX)
' 標準出力のStreamを取得して加工した画像を書き込む
image.Save(Console.OpenStandardOutput(), ImageFormat.Jpeg)
End Using
End Sub
End Class
>sample.exe < sample.jpg > mirror.jpg
OpenStandardInput/OpenStandardOutput/OpenStandardErrorの各メソッドで得られる標準ストリームのStreamをラップすることにより、暗号化や圧縮・バッファリングなどの機能を付け加えることもできます。
次の例ではbase64
コマンドに似たプログラムを実装しています。 CryptoStreamを使って標準入出力のStreamをラップすることにより、標準入力から読み込んだ内容をBASE64エンコード/デコードして標準出力に書き込んでいます。
using System;
using System.IO;
using System.Security.Cryptography;
class Sample {
static void Main(string[] args)
{
// コマンドライン引数に-dもしくは--decodeが指定されている場合はデコードを行う
var decode = false;
foreach (var arg in args) {
if (arg == "-d" || arg == "--decode")
decode = true;
}
Stream input, output;
if (decode) {
// BASE64デコードする場合
// 標準入力から読み込みを行い、FromBase64TransformによってBASE64デコードを行うCryptoStreamを入力元ストリームとする
input = new CryptoStream(Console.OpenStandardInput(), new FromBase64Transform(), CryptoStreamMode.Read);
// 標準出力を出力先ストリームとする
output = Console.OpenStandardOutput();
}
else {
// BASE64エンコードする場合
// 標準入力を入力元ストリームとする
input = Console.OpenStandardInput();
// ToBase64TransformによってBASE64エンコードを行い、標準出力へ書き込むCryptoStreamを出力先ストリームとする
output = new CryptoStream(Console.OpenStandardOutput(), new ToBase64Transform(), CryptoStreamMode.Write);
}
// 入力元ストリームの内容を出力先ストリームに'コピー'する
// (コピーを行う際、CryptoStreamによってデコード/エンコード処理が行われる)
input.CopyTo(output);
output.Close();
}
}
Imports System
Imports System.IO
Imports System.Security.Cryptography
Class Sample
Shared Sub Main(ByVal args As String())
' コマンドライン引数に-dもしくは--decodeが指定されている場合はデコードを行う
Dim decode As Boolean = false
For Each arg As String In args
If arg = "-d" OrElse arg = "--decode" Then decode = True
Next
Dim input, output As Stream
If decode Then
' BASE64デコードする場合
' 標準入力から読み込みを行い、FromBase64TransformによってBASE64デコードを行うCryptoStreamを入力元ストリームとする
input = New CryptoStream(Console.OpenStandardInput(), New FromBase64Transform(), CryptoStreamMode.Read)
' 標準出力を出力先ストリームとする
output = Console.OpenStandardOutput()
Else
' BASE64エンコードする場合
' 標準入力を入力元ストリームとする
input = Console.OpenStandardInput()
' ToBase64TransformによってBASE64エンコードを行い、標準出力へ書き込むCryptoStreamを出力先ストリームとする
output = new CryptoStream(Console.OpenStandardOutput(), new ToBase64Transform(), CryptoStreamMode.Write)
End If
' 入力元ストリームの内容を出力先ストリームに'コピー'する
' (コピーを行う際、CryptoStreamによってデコード/エンコード処理が行われる)
input.CopyTo(output)
output.Close()
End Sub
End Class
>type sample.txt Hello, world! >type sample.txt | sample.exe SGVsbG8sIHdvcmxkIQo= >type sample.txt | sample.exe | sample.exe -d Hello, world!
ストリームのラップについて、また暗号化や圧縮などのフォーマット変換、バッファリングなどの機能を付け加える方法等についてはストリームの基本とStreamクラス §.データフォーマットの変換やバッファリングなどの機能を追加するStream派生クラスも参照してください。
取得した標準ストリームを使う例として、コマンドラインオプションで標準入力とファイル入力を切り替える例を実装しているMD5ハッシュ文字列の作成 §.MD5クラスを使ってmd5sumコマンドを実装するもあわせてご覧ください。
標準ストリームのリダイレクト
SetIn/SetOut/SetErrorの各メソッドを使うと、実行時に標準ストリームを任意のTextReader/Writerへとリダイレクトすることができます。
標準ストリームのリダイレクトを行うと、Console.WriteLineやReadLineなどのメソッドの入出力先は、リダイレクト先として指定されたTextReader/Writerへと変更されます。
次の例ではSetOutメソッドを使って標準出力の出力先を実行時に開いたファイルに変更しています。
using System;
using System.IO;
class Sample {
static void Main()
{
// この内容はデフォルトの標準出力に書き込まれる
Console.WriteLine("Hello, world!");
// ファイルstdout.txtへ書き込むStreamWriterを作成する
var writer = new StreamWriter("stdout.txt");
// 書き込みの度にバッファをフラッシュさせるためにAutoFlushをtrueにする
writer.AutoFlush = true;
// 作成したStreamWriterを標準出力の出力先にする
Console.SetOut(writer);
// この内容はファイルstdout.txtに書き込まれる
Console.WriteLine("こんにちは、世界!");
}
}
Imports System
Imports System.IO
Class Sample
Shared Sub Main()
' この内容はデフォルトの標準出力に書き込まれる
Console.WriteLine("Hello, world!")
' ファイルstdout.txtへ書き込むStreamWriterを作成する
Dim writer As New StreamWriter("stdout.txt")
' 書き込みの度にバッファをフラッシュさせるためにAutoFlushをTrueにする
writer.AutoFlush = True
' 作成したStreamWriterを標準出力の出力先にする
Console.SetOut(writer)
' この内容はファイルstdout.txtに書き込まれる
Console.WriteLine("こんにちは、世界!")
End Sub
End Class
>sample.exe Hello, world! >type stdout.txt こんにちは、世界!
Console.In/Out/Errorプロパティから取得できるTextReader/Writerをリダイレクトする前に退避しておき、あとで再度リダイレクト先として設定することにより、一度リダイレクトした標準ストリームの入出力先を元の状態に戻すことができます。
using System;
using System.IO;
class Sample {
static void Main()
{
// 初期状態での標準出力の出力先を退避しておく
var stdout = Console.Out;
// ファイルstdout.txtへ書き込むStreamWriterを作成する
var writer = new StreamWriter("stdout.txt");
// 書き込みの度にバッファをフラッシュさせるためにAutoFlushをtrueにする
writer.AutoFlush = true;
// 作成したStreamWriterを標準出力の出力先にする
Console.SetOut(writer);
// この内容はファイルstdout.txtに書き込まれる
Console.WriteLine("Hello, world!");
// 標準出力の出力先を元に戻す
Console.SetOut(stdout);
// この内容は(初期状態での)標準出力に書き込まれる
Console.WriteLine("こんにちは、世界!");
}
}
Imports System
Imports System.IO
Class Sample
Shared Sub Main()
' 初期状態での標準出力の出力先を退避しておく
Dim stdout As TextWriter = Console.Out
' ファイルstdout.txtへ書き込むStreamWriterを作成する
Dim writer As New StreamWriter("stdout.txt")
' 書き込みの度にバッファをフラッシュさせるためにAutoFlushをTrueにする
writer.AutoFlush = True
' 作成したStreamWriterを標準出力の出力先にする
Console.SetOut(writer)
' この内容はファイルstdout.txtに書き込まれる
Console.WriteLine("Hello, world!")
' 標準出力の出力先を元に戻す
Console.SetOut(stdout)
' この内容は(初期状態での)標準出力に書き込まれる
Console.WriteLine("こんにちは、世界!")
End Sub
End Class
>sample.exe こんにちは、世界! >type stdout.txt Hello, world!
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は、標準出力のリダイレクト先として設定することにより、出力される内容を一切破棄する(何も出力させない)ことができます。
using System;
using System.IO;
class Sample {
static void Main()
{
// 標準出力の出力先をTextWriter.Nullに変更する
// (標準出力をnullデバイスにリダイレクトした場合と似た効果となる)
Console.SetOut(TextWriter.Null);
// この内容はTextWriter.Nullに書き込まれる
// (TextWriter.Nullは'なにもしない'ので、実際には'どこにも'/'なにも'出力されない)
Console.WriteLine("Hello, world!");
}
}
Imports System
Imports System.IO
Class Sample
Shared Sub Main()
' 標準出力の出力先をTextWriter.Nullに変更する
' (標準出力をnullデバイスにリダイレクトした場合と似た効果となる)
Console.SetOut(TextWriter.Null)
' この内容はTextWriter.Nullに書き込まれる
' (TextWriter.Nullは'なにもしない'ので、実際には'どこにも'/'なにも'出力されない)
Console.WriteLine("Hello, world!")
End Sub
End Class
標準ストリームがリダイレクトされているか調べる
.NET Framework 4.5以降では、IsInputRedirected/IsOutputRedirected/IsErrorRedirectedの各プロパティを参照することにより、自プロセスの標準ストリームがリダイレクトされているかどうかを知ることができるようになっています。
これらのプロパティは、コマンドラインで標準ストリームのパイプ・リダイレクトを行った場合にtrueとなるほか、SetIn/SetOut/SetErrorメソッドによってリダイレクトを行った場合もtrueとなります。
using System;
class Sample {
static void Main()
{
// 各標準ストリームがリダイレクトされているかどうかを調べる
Console.WriteLine("IsInputRedirected: {0}", Console.IsInputRedirected);
Console.WriteLine("IsOutputRedirected: {0}", Console.IsOutputRedirected);
Console.WriteLine("IsErrorRedirected: {0}", Console.IsErrorRedirected);
}
}
Imports System
Class Sample
Shared Sub Main()
' 各標準ストリームがリダイレクトされているかどうかを調べる
Console.WriteLine("IsInputRedirected: {0}", Console.IsInputRedirected)
Console.WriteLine("IsOutputRedirected: {0}", Console.IsOutputRedirected)
Console.WriteLine("IsErrorRedirected: {0}", Console.IsErrorRedirected)
End Sub
End Class
>sample.exe IsInputRedirected: False IsOutputRedirected: False IsErrorRedirected: False >type sample.txt | sample.exe IsInputRedirected: True IsOutputRedirected: False IsErrorRedirected: False >sample.exe | more IsInputRedirected: False IsOutputRedirected: True IsErrorRedirected: False >sample.exe < sample.txt IsInputRedirected: True IsOutputRedirected: False IsErrorRedirected: False >sample.exe > stdout.txt >type stdout.txt IsInputRedirected: False IsOutputRedirected: True IsErrorRedirected: False >test.exe 2> stderr.txt IsInputRedirected: False IsOutputRedirected: False IsErrorRedirected: 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を用いる、といったことができます。
using System;
using System.IO;
using System.Text;
class Sample {
static void Main()
{
// 標準入力のエンコーディングにShift_JISを用いる
Console.InputEncoding = shift_jis;
// 標準出力のエンコーディングにUTF-8を用いる
Console.OutputEncoding = Encoding.UTF8;
// 標準入力の内容すべてを読み込み標準出力に書き込む
// (標準入出力を介してShift_JISからUTF-8への変換が行われる)
Console.Out.Write(Console.In.ReadToEnd());
}
static readonly Encoding shift_jis =
#if NETFRAMEWORK
Encoding.GetEncoding("shift_jis");
#else
// `dotnet add sample.csproj package System.Text.Encoding.CodePages`
CodePagesEncodingProvider.Instance.GetEncoding("shift_jis");
#endif
}
Imports System
Imports System.IO
Imports System.Text
Class Sample
Shared Sub Main()
' 標準入力のエンコーディングにShift_JISを用いる
Console.InputEncoding = shift_jis
' 標準出力のエンコーディングにUTF-8を用いる
Console.OutputEncoding = Encoding.UTF8
' 標準入力の内容すべてを読み込み標準出力に書き込む
' (標準入出力を介してShift_JISからUTF-8への変換が行われる)
Console.Out.Write(Console.In.ReadToEnd())
End Sub
#If NETFRAMEWORK Then
Shared ReadOnly shift_jis As Encoding = Encoding.GetEncoding("shift_jis")
#Else
' `dotnet add sample.vbproj package System.Text.Encoding.CodePages`
Shared ReadOnly shift_jis As Encoding = CodePagesEncodingProvider.Instance.GetEncoding("shift_jis")
#End If
End Class
>chcp 現在のコード ページ: 932 >type input.shiftjis.txt こんにちは、世界! Shift_JISのファイルinput.shiftjis.txtを標準入力に与える UTF-8で出力される標準出力の内容をoutput.utf8.txtに書き込む >sample.exe < input.shiftjis.txt > output.utf8.txt >type output.utf8.txt 縺薙s縺ォ縺。縺ッ縲∽ク也阜・・ >chcp 65001 Active code page: 65001 >type output.utf8.txt こんにちは、世界!
コンソールの文字コードを変更するコマンドchcp
についてはMS-DOSコマンドプロンプトTips §.文字コードの変更を参照してください。
なお、ErrorEncodingプロパティは存在しないため、標準エラーのエンコーディングを指定・変更することはできません。 SetErrorメソッドを使えば任意のTextWriterを指定できるため、目的のエンコーディングを使用するStreamWriterを作成して標準エラーのリダイレクト先として指定する、といったことはできます。
OutputEncodingプロパティにUTF-8などのエンコーディングを指定すると、標準出力にBOM(Byte Order Mark)が出力される場合があります。 この動作はランタイムの種類や実行環境によって異なります。 詳細についてはEncodingクラスとBOMありなしの制御 §.Consoleクラスを参照してください。