标准流

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 可以使用标准输入为沟通接口,以便交互式程序能理解图形用户界面程序。

另见

编辑

参考

编辑

外部链接

编辑