標準ストリーム

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索
標準ストリーム(入力、出力、エラー出力)

標準ストリーム: standard streams)は、UNIXおよびUnix系オペレーティングシステムや一部のプログラミング言語インタフェースにおいて、プログラムとその環境(通常は端末)を実行前から接続している入出力チャネルである。現在では3つの入出力があり、標準入力 (standard input)、標準出力 (standard output)、標準エラー出力 (standard error) と呼ばれている。かつては通信回線に対応する標準補助入出力 (stdaux)、帳票印字を出力する装置に対応する標準プリンタ出力 (stdprn)も用意されていた。

背景[編集]

UNIX以前の多くのオペレーティングシステムでは、プログラムは明示的に適当な入出力に接続する必要があった。多くのシステムにはOS固有の複雑な事情があり、環境設定をしたり、ローカルなファイルテーブルにアクセスしたり、必要なデータセットを指定したり、カードリーダー、磁気テープドライブ、ディスクドライブ、ラインプリンタ、カードパンチ、対話型端末などを正しく扱うといったプログラミング以前のハードルが多数存在した。

UNIXはこの状況に対していくつかの重要な進化を遂げている。その1つが「抽象デバイス (abstract device)」である。これはプログラム自体がやり取りするデバイスに関する知識を持たなくて済むようにしたものである。古いOSでは、プログラマはレコード構造を知っておく必要があり、直交性のないことが多いデータ意味論やデバイス制御を扱う必要があった。UNIXはデータストリームという概念によってこのような複雑さを排除した。データストリームとは、逐次的なデータバイト列であり、End Of File までリード可能である。プログラムはまた、好きなだけバイト列を出力でき、事前にバイト数を宣言しておく必要もないし、それらがどのようにグループ化されているかを宣言する必要もない。

もう1つのUNIXの成し遂げたブレークスルーは、自動的に入力と出力を関連付けることであり、典型的な入力-処理-出力型プログラムでは入出力の設定を何もする必要がない。対照的にそれ以前のOSでは、複雑なジョブ制御言語を使ってコネクションを確立するか、それとほぼ同等のことをプログラム本体で行う必要があった。

UNIXが標準ストリームを提供したことで、そのC言語実行環境もそれをサポートするようになった。結果として、多くのC言語実行環境(および派生言語の実行環境)はOSが何であっても同等な機能を提供するようになっている。

標準入力 (stdin)[編集]

標準入力はプログラムに入ってくるデータ(テキストが多い)である。プログラムは read 操作を使ってデータ転送を要求する。全てのプログラムが入力を要求するわけではない。例えば dirls プログラム(ディレクトリ内のファイル名を表示する)は、標準入力からのデータを使わないで処理を行う。

リダイレクトしない限り、標準入力はプログラムを起動した端末のキーボードになっている。

標準入力のファイル記述子は0(ゼロ)である。POSIX<unistd.h> では STDIN_FILENO と定義されている。対応する <stdio.h> での変数は FILE* stdin<iostream> での変数は std::cin である。

標準出力 (stdout)[編集]

標準出力はプログラムが書き出すデータのストリームである。プログラムは write 操作を使ってデータ転送を要求する。全てのプログラムが出力を要求するわけではない。例えばファイル改名コマンド(mvmoveren など)は何も出力しない。

リダイレクトしない限り、標準出力はプログラムを起動した端末のディスプレイになっている。

標準出力のファイル記述子は1である。POSIX<unistd.h> では STDOUT_FILENO と定義されている。対応する <stdio.h> での変数は FILE* stdout<iostream> での変数は std::cout である。

標準エラー出力 (stderr)[編集]

標準エラー出力は、エラーメッセージや診断メッセージを出力するためのもう1つの出力ストリームである。標準出力とは独立しているため、一方だけをリダイレクトすることができる。デフォルトでは端末(のディスプレイ)になっており、標準出力がリダイレクトされていて画面に表示されなくとも、エラーメッセージだけはユーザーが目にするようになっている。例えば、パイプで出力が他のプログラムの入力に接続されている場合でも、標準エラー出力は直接端末のディスプレイに届く。

標準出力と標準エラー出力を同じ出力先(端末など)にリダイレクトすることもよくある。バッファが関与しない場合、メッセージはプログラムが書いた順序で現れる。典型的な例として、標準エラー出力がバッファリングされておらず、標準出力が行単位でバッファリングされている場合、後から標準エラー出力に書かれたメッセージが先に端末上に表示されることがある(標準出力のバッファが満杯になっていない場合)。

標準エラー出力のファイル記述子は2である。POSIX<unistd.h> では STDERR_FILENO と定義されている。対応する <stdio.h> での変数は FILE* stderr<iostream> での変数は2つあり std::cerrstd::clog である。前者はバッファリングされておらず、後者はC++の他のストリームと同様にバッファリングされている。

多くのシェルでは、標準出力と標準エラー出力を同じファイルにリダイレクトする場合、以下のように記述する。

 >& filename

Bourne Shell 系のシェルでは、標準エラー出力を標準出力と同じようにリダイレクトする場合、次のように記述できる。

 2>&1

歴史[編集]

1950年代: FORTRAN[編集]

FORTRANにもUNIXのようなファイル記述子があり、UNIT=5 が stdin、UNIT=6 が stdout を表す。

! FORTRAN 77 example
      PROGRAM MAIN
      READ(UNIT=5,*)NUMBER
      WRITE(UNIT=6,'(F5.3)')' NUMBER IS: ',NUMBER
      END

1960年: ALGOL 60[編集]

ALGOL 60 には、標準ストリーム(ファイルアクセス)の概念が存在しない。

1968年: ALGOL 68[編集]

ALGOL 68 では、入力 (input) と出力 (output) をあわせて transput と呼ぶ。Cornelis H. A. Koster はtransput 標準を定義した。この標準には stand instand outstand errorstand back がある。

例:

# ALGOL 68 example #
main:(
  REAL number;
  getf(stand in,($g$,number));
  printf(($"Number is: "g(6,4)"OR "$,number)); # OR #
  putf(stand out,($" Number is: "g(6,4)"!"$,number));
  newline(stand out)
)
入力: 出力:
3.14159
Number is: +3.142 OR Number is: +3.142!

1970年代: CとUnix[編集]

C言語では、stdin、stdout、stderr のストリームはUnixのファイル記述子 0、1、2 にそれぞれ対応する。

1995年: Java[編集]

Javaでは、標準ストリームは System.in(stdin)、System.out(stdout)、System.err(stderr)で参照される。

public static void main(String args[]) {
    try {
        BufferedReader br = 
          new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        double number = Double.parseDouble(s);
        System.out.println("Number is:" + number);
    } catch (Exception e) {
        System.err.println("Error:" + e.getMessage());
    }
}

2000年代: .NET[編集]

C#などの.NET言語では、標準ストリームは System.Console.In(stdin)、System.Console.Out(stdout)、System.Console.Error(stderr)で参照される。stdin および stdout ストリームの基本的な読み書きの場合、クラス System.Console を使って直接アクセスすることもできる(つまり、System.Console.Out.WriteLine() の代わりに System.Console.WriteLine() を使える)。

System.Console.InSystem.Console.OutSystem.Console.ErrorSystem.IO.TextReader (stdin) および System.IO.TextWriter (stdout, stderr) オブジェクトであり、テキストベースの標準ストリームにしかアクセスできない。標準ストリームへの完全バイナリアクセスには System.IO.Stream オブジェクトを使う必要があり、それぞれ System.Console.OpenStandardInput()System.Console.OpenStandardOutput()System.Console.OpenStandardError() で得られる。

// C# example
public static int Main(string[] args)
{
    try {
        string s = System.Console.In.ReadLine();
        double number = double.Parse(s);
        System.Console.Out.WriteLine("Number is: {0:F3}", number);
        return 0;
 
    // If Parse() threw an exception
    } catch (System.ArgumentNullException) { 
        System.Console.Error.WriteLine("No number was entered!");
    } catch (System.FormatException) {
        System.Console.Error.WriteLine("The specified value is not a valid number!");
    } catch (System.OverflowException) {
        System.Console.Error.WriteLine("The specified number is too big!");
    }
 
    return -1;
}
' Visual Basic .NET example
 
Public Function Main() As Integer
    Dim number As Double
    Dim s As String
 
    Try
        s = System.Console.In.ReadLine()
        number = CDbl(s)
        System.Console.Out.WriteLine("Number is: {0:F3}", number)
        Return 0
    Catch e As System.InvalidCastException
        ' if CDbl() threw an exception
        System.Console.Error.WriteLine("No number was entered!")
        Return 1
    End Try
End Function

System.Diagnostics.Process クラスを使うと、そのインスタンスプロパティ StandardInputStandardOutputStandardError を使ってそのプロセスの標準ストリームにアクセスできる。

GUI[編集]

グラフィカルユーザインタフェース (GUI) では滅多に標準ストリームを使わない。当然、GUIプログラムをリダイレクトしたり、GUIプログラムでパイプを使うことはない。GUIにとって標準ストリームに近いのはコピー・アンド・ペーストであろう。しかし、ユーザーの操作を必要とするため、多数の「ペースト」を行うのは効率的ではない。特筆すべき例外としてdwmというタイル型ウィンドウマネージャでは、stdout 上のデータをステータスバーに直接表示する。

特にUnix系の一部のGUIプログラムは、デバッグ情報を標準エラー出力に書き込んでいることがある。また、標準入力にファイルを指定する形式で働くものもあり、Unix系のメディアプレーヤーに多い。

GTK-serverでは、GUIを構築するインタプリタ型プログラムとのインタフェースにstdinを使うことができる。

関連項目[編集]

参考文献[編集]

外部リンク[編集]