En programación de computadoras , los flujos estándar son canales de comunicación de entrada y salida [1] preconectados entre un programa de computadora y su entorno cuando comienza la ejecución. Las tres conexiones de entrada/salida (E/S) se denominan entrada estándar ( stdin ), salida estándar ( stdout ) y error estándar ( stderr ). Originalmente, la E/S se realizaba a través de una consola del sistema conectada físicamente (entrada a través del teclado, salida a través del monitor), pero las transmisiones estándar abstraen esto. Cuando un comando se ejecuta a través de un shell interactivo , las secuencias generalmente se conectan al terminal de texto en el que se ejecuta el shell, pero se pueden cambiar con una redirección o una canalización . De manera más general, un proceso hijo hereda los flujos estándar de su proceso padre .
Los usuarios generalmente conocen los flujos estándar como canales de entrada y salida que manejan datos provenientes de un dispositivo de entrada o que escriben datos desde la aplicación. Los datos pueden ser texto con cualquier codificación o datos binarios . Cuando un programa se ejecuta como demonio , su flujo de errores estándar se redirige a un archivo de registro, generalmente con fines de análisis de errores.
Los flujos se pueden utilizar para encadenar aplicaciones, lo que significa que el flujo de salida de un programa se puede redirigir para que sea el flujo de entrada de otra aplicación. En muchos sistemas operativos, esto se expresa enumerando los nombres de las aplicaciones, separados por el carácter de barra vertical, por esta razón a menudo se le llama carácter de canalización . Un ejemplo bien conocido es el uso de una aplicación de paginación , como more , que proporciona al usuario control sobre la visualización del flujo de salida en la pantalla.
En la mayoría de los sistemas operativos anteriores a Unix , los programas tenían que conectarse explícitamente a los dispositivos de entrada y salida apropiados. Las complejidades específicas del sistema operativo hicieron que esta fuera una tarea de programación tediosa. En muchos sistemas era necesario obtener control de la configuración del entorno, acceder a una tabla de archivos local, determinar el conjunto de datos deseado y manejar el hardware correctamente en el caso de un lector de tarjetas perforadas , una unidad de cinta magnética, una unidad de disco , una impresora de líneas , una perforadora de tarjetas. , o terminal interactivo.
Uno de los varios avances innovadores de Unix fueron los dispositivos abstractos , que eliminaron la necesidad de que un programa supiera o le importara con qué tipo de dispositivos se estaba comunicando [ cita requerida ] . Los sistemas operativos más antiguos imponían al programador una estructura de registros y, con frecuencia, una semántica de datos y un control de dispositivos no ortogonales . Unix eliminó esta complejidad con el concepto de flujo de datos: una secuencia ordenada de bytes de datos que se puede leer hasta el final del archivo . Un programa también puede escribir bytes según lo desee y no es necesario, y no puede declarar fácilmente su recuento o agrupación.
Otro avance de Unix fue asociar automáticamente la entrada y la salida al teclado y la pantalla del terminal, respectivamente, de forma predeterminada [ cita necesaria ] : el programa (y el programador) no hizo absolutamente nada para establecer la entrada y la salida para un programa típico de proceso de entrada y salida ( a menos que elija un paradigma diferente). Por el contrario, los sistemas operativos anteriores generalmente requerían algún lenguaje de control de trabajo (a menudo complejo ) para establecer conexiones, o la carga equivalente tenía que ser orquestada por el programa. [ cita necesaria ]
Dado que Unix proporcionaba flujos estándar, el entorno de ejecución de Unix C estaba obligado a soportarlo también. Como resultado, la mayoría de los entornos de ejecución de C (y los descendientes de C ), independientemente del sistema operativo, proporcionan una funcionalidad equivalente.
La entrada estándar es una secuencia desde la cual un programa lee sus datos de entrada. El programa solicita transferencias de datos mediante el uso de la operación de lectura . No todos los programas requieren entrada de flujo. Por ejemplo, los programas dir y ls (que muestran los nombres de los archivos contenidos en un directorio) pueden tomar argumentos de línea de comandos , pero realizan sus operaciones sin ninguna entrada de datos de flujo.
A menos que se redirija , la entrada estándar se hereda del proceso principal. En el caso de un shell interactivo, generalmente está asociado con el dispositivo de entrada de un terminal (o pseudo terminal ) que en última instancia está vinculado al teclado de un usuario .
En los sistemas POSIX , el descriptor de archivo para la entrada estándar es 0 (cero); la definición POSIX es ; la abstracción de C correspondiente se proporciona a través de la variable global. De manera similar, la variable de tipo global de C++ proporciona una abstracción a través de flujos de C++ . Existen abstracciones similares en las bibliotecas de E/S estándar de prácticamente todos los lenguajes de programación .<unistd.h>
STDIN_FILENO
<stdio.h>
FILE* stdin
std::cin
<iostream>
La salida estándar es una secuencia en la que un programa escribe sus datos de salida. El programa solicita la transferencia de datos con la operación de escritura . No todos los programas generan resultados. Por ejemplo, el comando de cambio de nombre de archivo (también llamado mv , move o ren ) no dice nada sobre el éxito.
A menos que se redirija , la salida estándar se hereda del proceso principal. En el caso de un shell interactivo, suele ser el terminal de texto que inició el programa.
El descriptor de archivo para la salida estándar es 1 (uno); la definición POSIX es ; la variable C correspondiente es ; De manera similar, la variable C++ es .<unistd.h>
STDOUT_FILENO
<stdio.h>
FILE* stdout
<iostream>
std::cout
El error estándar es otro flujo de salida que suelen utilizar los programas para generar mensajes de error o diagnósticos. Es una transmisión independiente de la salida estándar y se puede redirigir por separado.
Esto resuelve el problema de semipredicado , permitiendo distinguir la salida y los errores, y es análogo a una función que devuelve un par de valores; consulte Problema de semipredicado: retorno con múltiples valores . El destino habitual es el terminal de texto que inició el programa para brindar la mejor oportunidad de ser visto incluso si se redirige la salida estándar (por lo que no se observa fácilmente). Por ejemplo, la salida de un programa en una canalización se redirige a la entrada del siguiente programa o a un archivo de texto, pero los errores de cada programa siguen yendo directamente al terminal de texto para que el usuario pueda revisarlos en tiempo real. [2]
Es aceptable y normal dirigir la salida estándar y el error estándar al mismo destino, como la terminal de texto. Los mensajes aparecen en el mismo orden en que el programa los escribe, a menos que se trate de almacenamiento en búfer . Por ejemplo, en situaciones comunes, el flujo de error estándar no tiene búfer, pero el flujo de salida estándar tiene búfer de línea; en este caso, el texto escrito en error estándar más tarde puede aparecer antes en el terminal, si el búfer de flujo de salida estándar aún no está lleno.
POSIX define el descriptor de archivo para el error estándar como 2 (dos); el archivo de encabezado <unistd.h> proporciona el símbolo ; [3] la variable C correspondiente es . El encabezado estándar de C++ proporciona dos variables asociadas con esta secuencia: y , la primera sin almacenamiento en búfer y la segunda usando el mismo mecanismo de almacenamiento en búfer que todas las demás secuencias de C++.STDERR_FILENO
<stdio.h>
FILE* stderr
<iostream>
std::cerr
std::clog
Los shells estilo Bourne permiten redirigir el error estándar al mismo destino al que se dirige la salida estándar.
2>&1
Los shells de estilo csh permiten redirigir el error estándar al mismo destino al que se dirige la salida estándar.
>&
El error estándar se agregó a Unix en la década de 1970 después de que varias ejecuciones de fotocomposición desperdiciadas terminaron con mensajes de error que se componían en lugar de mostrarse en la terminal del usuario. [4]
Fortran tiene el equivalente a los descriptores de archivos de Unix: por convención, muchas implementaciones de Fortran usan números de unidad UNIT=5
para stdin, UNIT=6
stdout y UNIT=0
stderr. En Fortran-2003, el ISO_FORTRAN_ENV
módulo intrínseco se estandarizó para incluir las constantes nombradas INPUT_UNIT
, OUTPUT_UNIT
y ERROR_UNIT
para especificar de forma portátil los números de unidad.
! Ejemplo de FORTRAN 77 PROGRAMA PRINCIPAL NÚMERO ENTERO LEER ( UNIDAD = 5 , * ) NÚMERO ESCRIBIR ( UNIDAD = 6 , '(A,I3)' ) ' EL NÚMERO ES: ' , FINAL DEL NÚMERO
! Programa de ejemplo de Fortran 2003 uso principal iso_fortran_env implícito ninguno entero :: número leído ( unidad = INPUT_UNIT , * ) número escrito ( unidad = OUTPUT_UNIT , ' (a,i3)' ) 'El número es:' , número final del programa
ALGOL 60 fue criticado por no tener acceso estándar a archivos. [ cita necesaria ]
Las instalaciones de entrada y salida de ALGOL 68 se denominaron colectivamente transput. [5] Koster coordinó la definición del estándar de transputación . El modelo incluía tres canales estándar: stand in
, stand out
y stand back
.
En el lenguaje de programación C , los flujos de entrada, salida y error estándar se adjuntan a los descriptores de archivos Unix existentes 0, 1 y 2 respectivamente. [6] En un entorno POSIX , se deben utilizar las definiciones < unistd.h > STDIN_FILENO , STDOUT_FILENO o STDERR_FILENO en lugar de números mágicos . También se proporcionan punteros de archivo stdin , stdout y stderr .
Ken Thompson (diseñador e implementador del sistema operativo Unix original) modificó la clasificación en la Versión 5 de Unix para aceptar "-" como representación de entrada estándar, que se extendió a otras utilidades y se convirtió en parte del sistema operativo como un archivo especial en la Versión 8 . Los diagnósticos fueron parte del resultado estándar hasta la Versión 6 , después de lo cual Dennis M. Ritchie creó el concepto de error estándar. [7]
En Java , los flujos estándar se denominan System.in
(para stdin), System.out
(para stdout) y System.err
(para stderr). [8]
public static void main ( String args [] ) { prueba { BufferedReader br = nuevo BufferedReader ( nuevo InputStreamReader ( System . in )); Cadena s = br . leerLínea (); número doble = Doble . parseDouble ( s ); Sistema . afuera . println ( "El número es:" + número ); } captura ( Excepción e ) { Sistema . errar . println ( "Error:" + e . getMessage ()); } }
En C# y otros lenguajes .NET , las secuencias estándar se denominan System.Console.In
(para stdin), System.Console.Out
(para stdout) y System.Console.Error
(para stderr). [9] Las capacidades básicas de lectura y escritura para los flujos stdin y stdout también son accesibles directamente a través de la clase System.Console
(por ejemplo, System.Console.WriteLine()
se pueden usar en lugar de System.Console.Out.WriteLine()
).
System.Console.In
, System.Console.Out
y System.Console.Error
son objetos System.IO.TextReader
(stdin) y System.IO.TextWriter
(stdout, stderr), que solo permiten el acceso a los flujos estándar subyacentes en forma de texto. El acceso binario completo a los flujos estándar se debe realizar a través de los System.IO.Stream
objetos devueltos por System.Console.OpenStandardInput()
y System.Console.OpenStandardOutput()
respectivamente System.Console.OpenStandardError()
.
// Ejemplo de C# public static int Main ( cadena [] args ) { prueba { cadena s = Sistema . Consola . En . Leerlínea (); número doble = doble . Analizar ( s ); Sistema . Consola . Afuera . WriteLine ( "El número es: {0:F3}" , número ); devolver 0 ; // Si Parse() arrojó una excepción } catch ( ArgumentNullException ) { System . Consola . Error . WriteLine ( "¡No se ingresó ningún número!" ); } captura ( FormatoException ) { Sistema . Consola . Error . WriteLine ( "¡El valor especificado no es un número válido!" ); } captura ( OverflowException ) { Sistema . Consola . Error . WriteLine ( "¡El número especificado es demasiado grande!" ); } retorno - 1 ; }
' Ejemplo de Visual Basic .NETFunción pública principal () como número entero Pruebe Dim s como cadena = sistema . Consola . [ En ] . ReadLine () Número atenuado Como Doble = Doble . Sistema de análisis ( s ) . Consola . Afuera . WriteLine ( "El número es: {0:F3}" , número ) Devuelve 0 ' Si Parse() arroja una excepción Catch ex As System . Sistema ArgumentNullException . Consola . [ Error ] . WriteLine ( "¡No se ingresó ningún número!" ) Captura ex2 como sistema . Sistema de excepción de formato . Consola . [ Error ] . WriteLine ( "¡El valor especificado no es un número válido!" ) Captura ex3 como sistema . Sistema de excepción de desbordamiento . Consola . [ Error ] . WriteLine ( "¡El número especificado es demasiado grande!" ) Fin del intento Retorno - 1 Función Final
Al aplicar la System.Diagnostics.Process
clase, se pueden usar las propiedades StandardInput
de instancia , StandardOutput
y StandardError
de esa clase para acceder a los flujos estándar del proceso.
El siguiente ejemplo, escrito en Python , muestra cómo redirigir la entrada estándar tanto a la salida estándar como a un archivo de texto.
#!/usr/bin/env pitón sistema de importación# Guarda la salida estándar actual para que podamos revertir sys.stdout# después de completar nuestra redirecciónstdin_fileno = sys . entrada estándarstdout_fileno = sys . salida estándar# Redirigir sys.stdout al archivosistema . salida estándar = abrir ( 'miarchivo.txt' , 'w' )ctr = 0para entradas en stdin_fileno : ctrs = cadena ( ctr ) # Imprime en la salida estándar redirigida () sistema . salida estándar . escribe ( ctrs + ") esto es para el redirigido --->" + inps + ' \n ' ) # Imprime en el controlador de salida estándar guardado real stdout_fileno . escribir ( ctrs + ") esto es al real --->" + inps + ' \n ' ) ctr = ctr + 1#Cerrar el archivosistema . salida estándar . cerca ()# Restaurar sys.stdout a nuestro antiguo administrador de archivos guardadossistema . salida estándar = salida_estándar_fileno
Las interfaces gráficas de usuario (GUI) no siempre utilizan los flujos estándar; lo hacen cuando las GUI son envoltorios de scripts subyacentes y/o programas de consola, por ejemplo, la GUI del administrador de paquetes Synaptic , que envuelve comandos apt en Debian y/o Ubuntu. Las GUI creadas con herramientas de secuencias de comandos como Zenity y KDialog por el proyecto KDE [10] utilizan stdin, stdout y stderr, y se basan en secuencias de comandos simples en lugar de una GUI completa programada y compilada en C/C++ usando Qt , GTK u otros. marco de widget propietario equivalente.
El menú Servicios , implementado en NeXTSTEP y Mac OS X , también es análogo a las transmisiones estándar. En estos sistemas operativos, las aplicaciones gráficas pueden proporcionar funcionalidad a través de un menú de todo el sistema que opera con la selección actual en la GUI, sin importar en qué aplicación.
Algunos programas GUI, principalmente en Unix, todavía escriben información de depuración en el error estándar. Otros (como muchos reproductores multimedia Unix) pueden leer archivos desde la entrada estándar. Los programas populares de Windows que abren una ventana de consola separada además de sus ventanas GUI son los emuladores pSX y DOSBox .
El servidor GTK puede utilizar stdin como interfaz de comunicación con un programa interpretado para realizar una GUI.
El paradigma Common Lisp Interface Manager "presenta" elementos GUI enviados a un flujo de salida extendido.