标准流

c语言

Unix类Unix系统中,如同某些编程语言接口一样,标准流是当一个计算机程序执行时,在它和它的环境间(典型为终端),事先连接的输入和输出频道。这三个I/O链接称作“标准输入”、“标准输出”和“标准错误输出”。

背景

在Unix之前的操作系统,程序必须明确指出链接到合适的输入和输出资料。对这当中的许多系统而言,这牵涉一些错综复杂而又与特定操作系统相关的事,是一件吓人的程式设计挑战。如控制环境设置、存取一个文件表格、决定区域资料集、和决定读卡器、磁带、磁碟、打印机、打卡机或交互式终端。

Unix 提供许多开创产的进步,其中之一是提供 抽象装置 :它免除了程序须要知道或在意它正与哪个装置沟通。 Unix 借由资料流的概念来消除这种复杂:一种资料字节的有序序列,直到读到文件结尾。程序员亦可依需求写入而无须宣告写入多少或如何组织。

另一个 Unix 突破为默认自动链接输入和输出-程序(和程序员)不用为了典型输入-处理-输出程序建立输入和输出。相对地,之前操作系统通常要求一些-有时复杂-工作控制语言Job Control Language英语Job Control Language)以建立链接,或者,相者近似于协调的责任。

既然 Unix 提供标准流,Unix C 的执行环境被要求要支持它。结果不管什么操作系统, C 的执行环境(及 C 的派生)都提供类似功能。

标准输入 (stdin)

标准输入是指输入至程序的资料(通常是文件)。程序要求以(read)操作来传输资料。并非所有程序都要求输入。如dirls程序(显示一个目录中的文件名)运行时不用任何输入。

除非重导向,输入是预期由 键盘获取的。

标准输入的文件描述符为 0。在POSIX <unistd.h> 的定义是 STDIN_FILENO;相对应的 <stdio.h> 变量为 FILE* stdin ;类似地, <iostream> 变量为 std::cin

标准输出 (stdout)

标准输出是指程序写输出资料的流。程序要求资料传输使用的运算。并非所有程序都要求输出。如mvren程序在成功完成时是沉默的。

除非重导向,输出为 终端

标准输出的文件描述符为 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::cerrstd::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 。 Cornelis H. A. Koster英语Cornelis H. A. Koster coordinated the definition of the transput standard. 这标准包含: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语言 中,标准输入、标准输出和标准错误输出分别连接到已存的 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 (标准输入)、System.Console.Out (标准输出)和System.Console.Error (标准错误)。stdin 和 stdout 的基本读写能力可以直接透过 System.Console 来存取(如 System.Console.WriteLine() 可以取代 System.Console.Out.WriteLine() )。

注意, System.Console.InSystem.Console.OutSystem.Console.ErrorSystem.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 时,可以使用 StandardInputStandardOutputStandardError 属性来存取程序的标准流。

Console 并非指 Dos 的命令行视窗。

图形用户界面

图形用户界面很少使用标准流。 重导图形用户界面或建立流水线是不实用的。 最近似的大概是从一个程序剪切(或复制)再贴到另一个。 既然需要人工用户的运作,移动大量的粘贴就不会特别有效率。 一个值得一提的例外为dwm铺砖式视窗管理器tiling window manager英语tiling window manager),其会将导入标准输入的资料显示到状态栏。

一些原本在 Unix 上的图形用户界面程序仍会写错误消息到标准错误输出。 其它可能会从标准输入获取文件,如许多 Unix 媒体播放程序。

GTK-Server英语GTK-Server 可以使用标准输入为沟通接口,以便交互式程序能理解图形用户界面程序。

另见

参考

外部链接