標準串流
在Unix和類Unix系統中,如同某些程式語言介面一樣,標準串流是當一個電腦程式執行時,在它和它的環境間(典型為終端),事先連接的輸入和輸出頻道。這三個I/O連結稱作“標準輸入”、“標準輸出”和“標準錯誤輸出”。
背景
在Unix之前的作業系統,程式必須明確指出連結到合適的輸入和輸出資料。對這當中的許多系統而言,這牽涉一些錯綜複雜而又與特定作業系統相關的事,是一件嚇人的程式設計挑戰。如控制環境設定、存取一個檔案表格、決定區域資料集、和決定讀卡機、磁帶、磁碟、列印機、打卡機或互動式終端機。
Unix 提供許多開創產的進步,其中之一是提供 抽象設備 :它免除了程式須要知道或在意它正與哪個設備溝通。 Unix 藉由資料串流的概念來消除這種複雜:一種資料位元組的有序序列,直到讀到檔案結尾。程式員亦可依需求寫入而無須宣告寫入多少或如何組織。
另一個 Unix 突破為預設自動連結輸入和輸出-程式(和程式設計師)不用為了典型輸入-處理-輸出程式建立輸入和輸出。相對地,之前作業系統通常要求一些-有時複雜-工作控制語言(en:Job Control Language)以建立連結,或者,相者近似於協調的責任。
既然 Unix 提供標準串流,Unix C 的執行環境被要求要支援它。結果不管什麼作業系統, C 的執行環境(及 C 的衍生)都提供類似功能。
標準輸入 (stdin)
標準輸入是指資料(通常是文件)走向程式。程式要求資料傳輸使用讀的運算。並非所有程式都要求輸入。如dir或ls程式(顯示一個目錄中的檔名)運行時不用任何輸入。
標準輸入的檔案描述子為 0 (零)。POSIX <unistd.h> 定義是 STDIN_FILENO;相對應的 <stdio.h> 變數為 FILE* stdin ;類似地, <iostream> 變數為 std::cin 。
標準輸出 (stdout)
標準輸出是指程式寫輸出資料的串流。程式要求資料傳輸使用寫的運算。並非所有程式都要求輸出。如mv或ren程式在成功完成時是沈默的。
標準輸出的檔案描述子為 1 (一)。POSIX <unistd.h> 定義是 STDOUT_FILENO;相對應的 <stdio.h> 變數為 FILE* stdout ;類似地, <iostream> 變數為 std::cout 。
標準錯誤輸出 (stderr)
標準錯誤輸出是另一個輸出串流,典型用於程式輸出錯誤訊息或診斷。它是獨立於標準輸出的串流且可以分別導向。通常目的地為終端。標準錯誤輸出是另一輸出串流,用於輸出錯誤訊息或診斷。它獨立於標準輸出,且可以分別被重導。常見的目的則為啟始這個程式的終端,即使其標準輸出被重導亦如此。例如:一個管線中的程式的輸出被重導到下一個程式,但錯誤訊息仍然直接流向文字終端機。
把標準輸出和標準錯誤輸出導到相同的目的地,如文字終端,是可以(且正常)的。訊息會以如同程式寫入的順序來出現,除非有用到緩衝。(例如,一個常見狀況是,當標準錯誤串流是未使用緩衝,但標準輸出串流是有使用的;在這情況下,如果標準輸出的緩衝區還沒滿的話,較慢寫到標準錯誤的文字可能會較早出現在終端。
標準錯誤輸出的檔案描述子為 2 ;POSIX <unistd.h> 定義為 STDERR_FILENO;相對的 <stdio.h> 變數 FILE* stderr。C++ <iostream> 標準表頭檔提供兩個相關的變數: std::cerr 和 std::clog,前者用於無緩衝的而後者使用和其它 C++ 串流相同的緩衝機制。
大部分殼程式允許使用
>& filename
將標準輸出和標準錯誤輸出重導向到相同的檔案。
Bourne-類殼程式允許使用
2>&1
將標準錯誤輸出重導向到標準輸出的目的。
年表
1950 年代: Fortran
Fortran 則提供類於 Unix 檔案描述子:UNIT=5
用於 stdin 、 UNIT=6
用於 stdout 和 UNIT=0
用於 stderr 。
! 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 的輸入和輸出機制合起來稱為 transput 。 en:Cornelis H. A. Koster coordinated the definition of the transput standard. 這標準包含: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) )
輸入: | 輸出: |
---|---|
3.14159 |
Number is: +3.142 OR Number is: +3.142! |
1970 年代: C 和 Unix
在 C語言 中,標準輸入、標準輸出和標準錯誤輸出分別連接到已存的 Unix 檔案描述子 0 、1 和 2。
1995: Java
在Java中, 標準串流被稱為 System.in(標準輸入)、System.out(標準輸出)和 System.err(標準錯誤輸)。
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());
}
}
2000s: .NET
在 C# 和其它 .NET 語言中,標準串流為 System.Console.In
(用於 stdin)、System.Console.Out
(用於 stdout)和System.Console.Error
(用於 stderr)。stdin 和 stdout 的基本讀寫能力可以直接透過 System.Console
來存取(如 System.Console.WriteLine()
可以被 System.Console.Out.WriteLine()
所取代)。
注意, System.Console.In
, System.Console.Out
和 System.Console.Error
是 System.IO.TextReader
(stdin) 和 System.IO.TextWriter
(stdout, stderr) 物件,只允許存取底層基於文件的標準串流。存取二位元標準串流要分別經由 System.Console.OpenStandardInput()
, System.Console.OpenStandardOutput()
和 System.Console.OpenStandardError()
所傳回的System.IO.Stream
。
// 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
類別時,可以使用
StandardInput
、StandardOutput
和 StandardError
屬性來存取程序的標準串流。
Console 並非指 Dos 的命令列視窗。
圖形使用者介面
圖形使用者介面很少使用標準串流。 重導圖形使用者介面或建立管線是不實用的。 最近似的大概是從一個程式剪下(或複製)再貼到另一個。 既然需要人工使用者的運作,移動大量的貼上就不會特別有效率。 一個值得一提的例外為dwm鋪磚式視窗管理器(en:tiling window manager),其會將導入標準輸入的資料顯示到狀態列。
一些原本在 Unix 上的圖形使用者介面程式仍會寫錯誤訊息到標準錯誤輸出。 其它可能會從標準輸入取得檔案,如許多 Unix 媒體播放程式。
en:GTK-Server 可以使用標準輸入為溝通介面,以便互動式程式能理解圖形使用者介面程式。
另見
參考
- 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)
- Video tutorial demonstrating stdout and stderr