标准流
在计算机编程中,标准流开始执行时,在计算机程序及其环境之间互连输入和输出通信渠道。三个输入/输出(I/O)连接称为标准输入( STDIN ),标准输出( STDOUT )和标准误差( STDERR )。最初是通过物理连接的系统控制台(通过键盘输入,通过监视器输出输入)发生的,但标准流则抽像这一点。当通过交互式外壳执行命令时,流通常连接到运行外壳的文本终端,但可以通过重定向或管道更改。更一般而言,儿童过程继承了其父过程的标准流。
应用
用户通常将标准流是输入和输出渠道,这些输入和输出通道处理来自输入设备的数据或从应用程序中写入数据。数据可以是带有任何编码或二进制数据的文本。在许多现代系统中,程序的标准错误流被重定向到日志文件,通常用于错误分析目的。
流可用于链接应用程序,这意味着一个程序的输出流可以重定向为输入流到另一个应用程序。在许多操作系统中,这是通过列出由垂直条形字符隔开的应用程序名称来表达的,因此通常称为管道字符。一个众所周知的示例是使用分页应用程序,例如更多地提供了对显示器上输出流的显示的用户控制。
背景
在UNIX之前的大多数操作系统中,程序必须明确连接到适当的输入和输出设备。 OS特定的复杂性使这是一项繁琐的编程任务。在许多系统上,有必要控制环境设置,访问本地文件表,确定预期的数据集,并在打孔卡读取器,磁带驱动器,磁盘驱动器,线条打印机,卡打孔的情况下正确处理硬件,或交互式终端。
Unix的几个开创性进步之一是抽象设备,它消除了程序知道或关心与之通信的设备的需求。较旧的操作系统被迫在程序员身上使用记录结构,并且经常非正交数据语义和设备控制。 Unix通过数据流的概念消除了这种复杂性:可以读取直到文件末尾的有序数据字节顺序。程序也可以根据需要编写字节,而无需编写,也不能轻易声明其计数或分组。
默认情况下,另一个UNIX突破是分别将输入和输出分别与终端键盘和终端显示相关联- 程序(和程序员)绝对没有任何作用来为典型的输入程序输出程序建立输入和输出(除非它选择了一个不同的范式)。相比之下,以前的操作系统通常需要一些(通常是复杂的 -工作控制语言)来建立联系,或者必须由该计划策划等效负担。
由于UNIX提供了标准流,因此UNIX C运行时环境也有义务也支持它。结果,大多数C运行时环境(和C的后代),无论操作系统如何,都提供等效功能。
标准输入(Stdin)
标准输入是程序从该流中读取其输入数据的流。该程序通过使用读取操作请求数据传输。并非所有程序都需要流输入。例如, DIR和LS程序(目录中包含的文件名)可能会采用命令行参数,但在没有任何流数据输入的情况下执行其操作。
除非重定向,否则标准输入将从父进程继承。在交互式外壳的情况下,通常与键盘相关。
标准输入的文件描述符为0(零); POSIX<unistd.h>
定义是STDIN_FILENO
;相应的c<stdio.h>
变量是FILE* stdin
;同样,C ++<iostream>
变量是std::cin
.
标准输出(Stdout)
标准输出是程序编写其输出数据的流。该程序请求使用写操作的数据传输。并非所有程序都会产生输出。例如,文件重命名命令(称为MV , MOVE或REN )对成功保持沉默。
除非重定向,否则标准输出将从父进程继承。在交互式外壳的情况下,通常是启动程序的文本终端。
标准输出的文件描述符为1(一); POSIX<unistd.h>
定义是STDOUT_FILENO
;相应的c<stdio.h>
变量是FILE* stdout
;同样,C ++<iostream>
变量是std::cout
.
标准错误(stderr)
标准错误是程序通常用于输出错误消息或诊断的另一个输出流。它是独立于标准输出的流,可以单独重定向。
这解决了半普遍的问题,可以区分输出和错误,并且类似于返回一对值的函数 - 请参见半Predicate问题:多价返回。通常的目的地是启动程序的文本终端,即使标准输出被重定向(因此不容易观察到),也可以提供最佳机会。例如,将管道中程序的输出重定向到下一个程序或文本文件的输入,但是每个程序中的错误仍然直接转到文本终端,以便用户可以实时审核它们。
将标准输出和标准误差直接到同一目的地(例如文本终端)是可以接受和正常的。除非涉及缓冲,否则消息以与程序写的顺序相同。例如,在常见的情况下,标准误差流是未封闭的,但标准输出流是线条缓冲。在这种情况下,如果标准输出流缓冲区尚未完整,则稍后将写入标准错误的文本可能会出现在终端上。
POSIX将标准错误的文件描述符定义为2(二); <unistd.h>标题文件提供符号STDERR_FILENO
;相应的c<stdio.h>
变量是FILE* stderr
。 C ++<iostream>
标准标头提供了与此流相关的两个变量:std::cerr
和std::clog
,前者使用与所有其他C ++流相同的缓冲机构,并使用后者。
Bourne式外壳允许将标准错误重定向到标准输出用于使用的同一目的地
2>&1
CSH-风格的外壳允许将标准错误重定向到标准输出用于使用的同一目的地
>&
在1970年代,在几次浪费的光型操作运行之后,标准错误被添加到UNIX中,而错误消息则在用户的终端上显示,而不是显示错误消息。
时间线
1950年代:fortran
FORTRAN等同于UNIX文件描述符:按照惯例,许多Fortran实现都使用单位号码UNIT=5
对于stdin,UNIT=6
对于Stdout和UNIT=0
对于stderr。在Fortran-2003中,固有的ISO_FORTRAN_ENV
模块被标准化以包括命名常数INPUT_UNIT
,OUTPUT_UNIT
, 和ERROR_UNIT
便便指定单位号。
! FORTRAN 77 example
PROGRAM MAIN
INTEGER NUMBER
READ(UNIT=5,*) NUMBER
WRITE(UNIT=6,'(A,I3)') ' NUMBER IS: ',NUMBER
END
! Fortran 2003 example
program main
use iso_fortran_env
implicit none
integer :: number
read (unit=INPUT_UNIT,*) number
write (unit=OUTPUT_UNIT,'(a,i3)') 'Number is: ', number
end program
1960年:阿尔戈尔60
Algol 60因没有标准文件访问而受到批评。
1968年:Algol 68
Algol 68的输入和输出设施统称为变速。 Koster协调了变速标准的定义。该模型包括三个标准渠道:stand in
,stand out
, 和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。在POSIX环境中,应使用< unistd.h >定义stdin_fileno , stdout_fileno或stderr_fileno而不是魔术数字。还提供了文件指针stdin , stdout和stderr 。
肯·汤普森(Ken Thompson)(原始UNIX操作系统的设计师兼实施者)在版本5 Unix中修改了“ - ”作为代表标准输入的“ - ”,这些输入传播到其他实用程序,并成为版本8中的特殊文件的操作系统的一部分。诊断是通过版本6的标准输出的一部分,此后Dennis M. Ritchie创建了标准错误的概念。
1995:爪哇
在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.WriteLine()
可以使用而不是System.Console.Out.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()
分别。
// 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 (ArgumentNullException) {
System.Console.Error.WriteLine("No number was entered!");
} catch (FormatException) {
System.Console.Error.WriteLine("The specified value is not a valid number!");
} catch (OverflowException) {
System.Console.Error.WriteLine("The specified number is too big!");
}
return -1;
}
' Visual Basic .NET example
Public Function Main() As Integer
Try
Dim s As String = System.Console.[In].ReadLine()
Dim number As Double = Double.Parse(s)
System.Console.Out.WriteLine("Number is: {0:F3}", number)
Return 0
' If Parse() threw an exception
Catch ex As System.ArgumentNullException
System.Console.[Error].WriteLine("No number was entered!")
Catch ex2 As System.FormatException
System.Console.[Error].WriteLine("The specified value is not a valid number!")
Catch ex3 As System.OverflowException
System.Console.[Error].WriteLine("The specified number is too big!")
End Try
Return -1
End Function
应用时System.Diagnostics.Process
一类可以使用实例属性StandardInput
,StandardOutput
, 和StandardError
该课程访问该过程的标准流。
2000-:Python(2或3)
以Python编写的以下示例显示了如何将标准输入重定向到标准输出和文本文件。
#!/usr/bin/env python
import sys
# Save the current stdout so that we can revert sys.stdout
# after we complete our redirection
stdin_fileno = sys.stdin
stdout_fileno = sys.stdout
# Redirect sys.stdout to the file
sys.stdout = open('myfile.txt', 'w')
ctr = 0
for inps in stdin_fileno:
ctrs = str(ctr)
# Prints to the redirected stdout ()
sys.stdout.write(ctrs + ") this is to the redirected --->" + inps + '\n')
# Prints to the actual saved stdout handler
stdout_fileno.write(ctrs + ") this is to the actual --->" + inps + '\n')
ctr = ctr + 1
# Close the file
sys.stdout.close()
# Restore sys.stdout to our old saved file handler
sys.stdout = stdout_fileno
吉斯
图形用户界面(GUI)并不总是使用标准流;当Guis是基础脚本和/或控制台程序的包装器时,例如突触软件包管理器GUI,它包装了Debian和/或Ubuntu中的APT命令。使用KDE Project的Zenity和Kdialog等脚本工具创建的GUI,使用Stdin,Stdout和Stderr,并基于简单的脚本,而不是使用QT , GTK或其他等效的Widget在C/C ++中编辑的完整GUI编程和编译框架。
在NextStep和Mac OS X上实现的服务菜单也类似于标准流。在这些操作系统上,图形应用程序可以通过在GUI中的当前选择中运行的全系统菜单来提供功能,无论在哪种应用程序中。
一些GUI程序(主要是在UNIX上)仍将调试信息写入标准错误。其他(例如许多UNIX媒体播放器)可能会从标准输入中读取文件。除了GUI窗口之外,开放单独的控制台窗口的流行Windows程序是模拟器PSX和DOSBOX 。
GTK-Server可以将STDIN用作具有解释程序的通信接口来实现GUI。
通用的LISP接口管理器范式“呈现” GUI元素发送到扩展输出流。