標準ストリーム

**標準ストリーム**（）とは、UNIXおよびUnix系オペレーティングシステムにおいて、プログラム（プロセス）とその実行環境との間でデータをやり取りするために、あらかじめ割り当てられている入出力経路の総称である。

通常、標準入力、標準出力、標準エラー出力の三つが定義され、端末、ファイル、パイプなど異なる入出力先を同一の方法で扱うことを可能にする。この仕組みは、プログラム同士を連結して処理を構成するパイプや入出力リダイレクトを支えるものであり、UNIX系システムの利用およびソフトウェア設計における基本機構となっている。

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

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

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

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

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

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

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

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

このストリームのデフォルト宛先はプログラムを起動した端末のディスプレイになっている。リダイレクトにより容易に宛先を変更できる。

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

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

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

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

## 歴史
### 1950年代: FORTRAN
FORTRANにもUNIXのようなファイル記述子があり、`UNIT=5`がstdin、`UNIT=6`がstdoutを表す。

```fortran
! 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 in`、`stand out`、`stand error`、`stand 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)
)
```


### 1970年代: CとUUNIX
C言語では、stdin、stdout、stderrのストリームはUNIXのファイル記述子 0、1、2にそれぞれ対応する。

### 1995年: Java
Javaでは、標準ストリームは (stdin)、 (stdout)、 (stderr) で参照される。

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

```csharp
// 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;
}
```



```vbnet
' 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`クラスを使うと、そのインスタンスプロパティ`StandardInput`、`StandardOutput`、`StandardError`を使ってそのプロセスの標準ストリームにアクセスできる。

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

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

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

## 関連項目
* リダイレクト (CLI)
* パイプ (コンピュータ)
* ストリーム (プログラミング)
* 入出力
* fgetc

## 参考文献
* *KRONOS 2.1 Reference Manual*, Control Data Corporation, Part Number 60407000, 1974
* *NOS Version 1 Applications Programmer's Instant*, Control Data Corporation, Part Number 60436000, 1978
* Level 68 Introduction to Programming on MULTICS, Honeywell Corporation, 1981
* Evolution of the MVS Operating System, IBM Corporation, 1981
* *Lions' Commentary on UNIX Sixth Edition*, John Lions, ISBN 1-57398-013-7, 1977
* Console Class, .NET Framework Class Library, Microsoft Corporation, 2008

## 外部リンク
* Standard Output Definition - by The Linux Information Project (LINFO)