В программировании компьютеров стандартные потоки — это предварительно подключенные каналы ввода и вывода [1] между компьютерной программой и ее средой, когда она начинает выполняться. Три соединения ввода/вывода (I/O) называются стандартным вводом ( stdin ), стандартным выводом ( stdout ) и стандартной ошибкой ( stderr ). Первоначально ввод/вывод осуществлялся через физически подключенную системную консоль (ввод через клавиатуру, вывод через монитор), но стандартные потоки абстрагируют это. Когда команда выполняется через интерактивную оболочку , потоки обычно подключаются к текстовому терминалу, на котором запущена оболочка, но могут быть изменены с помощью перенаправления или конвейера . В более общем смысле, дочерний процесс наследует стандартные потоки своего родительского процесса .
Пользователи обычно знают стандартные потоки как входные и выходные каналы, которые обрабатывают данные, поступающие с устройства ввода, или которые записывают данные из приложения. Данные могут быть текстом с любой кодировкой или двоичными данными . Когда программа запускается как демон , ее стандартный поток ошибок перенаправляется в файл журнала, как правило, для целей анализа ошибок.
Потоки могут использоваться для объединения приложений в цепочку, что означает, что выходной поток одной программы может быть перенаправлен в качестве входного потока для другого приложения. Во многих операционных системах это выражается перечислением имен приложений, разделенных символом вертикальной черты, по этой причине часто называемым символом конвейера . Хорошо известным примером является использование приложения для разбиения на страницы , такого как more , предоставляющего пользователю контроль над отображением выходного потока на дисплее.
В большинстве операционных систем, предшествовавших Unix , программы должны были явно подключаться к соответствующим устройствам ввода и вывода. Специфические для ОС тонкости делали это утомительной задачей программирования. Во многих системах было необходимо получить контроль над настройками среды, получить доступ к локальной таблице файлов, определить предполагаемый набор данных и правильно обращаться с оборудованием в случае считывателя перфокарт , накопителя на магнитной ленте , дисковода , линейного принтера , перфоратора или интерактивного терминала.
Одним из нескольких новаторских достижений Unix были абстрактные устройства , которые устранили необходимость для программы знать или заботиться о том, с какими устройствами она взаимодействует [ требуется ссылка ] . Старые операционные системы навязывали программисту структуру записи и часто неортогональную семантику данных и управление устройствами. Unix устранил эту сложность с помощью концепции потока данных: упорядоченной последовательности байтов данных, которые могут быть прочитаны до конца файла . Программа также может записывать байты по желанию и без необходимости и не может легко объявлять их количество или группировку.
Другим прорывом Unix было автоматическое связывание ввода и вывода с клавиатурой терминала и дисплеем терминала соответственно по умолчанию [ требуется цитата ] — программа (и программист) не делали абсолютно ничего, чтобы установить ввод и вывод для типичной программы ввода-обработки-вывода (если только она не выбирала другую парадигму). Напротив, предыдущие операционные системы обычно требовали некоторого — часто сложного — языка управления заданиями для установления соединений, или эквивалентная нагрузка должна была быть организована программой. [ требуется цитата ]
Поскольку Unix предоставлял стандартные потоки, среда выполнения Unix C также была обязана их поддерживать. В результате большинство сред выполнения C (и потомков C ), независимо от операционной системы, предоставляют эквивалентную функциональность.
Стандартный ввод — это поток, из которого программа считывает свои входные данные. Программа запрашивает передачу данных с помощью операции чтения . Не всем программам требуется потоковый ввод. Например, программы dir и ls (которые отображают имена файлов, содержащихся в каталоге) могут принимать аргументы командной строки , но выполнять свои операции без ввода потоковых данных.
Если не перенаправлено , стандартный ввод наследуется от родительского процесса. В случае интерактивной оболочки это обычно связано с устройством ввода терминала ( или псевдотерминала ), который в конечном итоге связан с клавиатурой пользователя .
В системах POSIX файловый дескриптор для стандартного ввода равен 0 (нулю); определение POSIX <unistd.h>
равно STDIN_FILENO
; соответствующая <stdio.h>
абстракция C предоставляется через FILE* stdin
глобальную переменную. Аналогично, глобальная std::cin
переменная C++ типа <iostream>
предоставляет абстракцию через потоки C++ . Аналогичные абстракции существуют в стандартных библиотеках ввода-вывода практически каждого языка программирования .
Стандартный вывод — это поток, в который программа записывает свои выходные данные. Программа запрашивает передачу данных с помощью операции записи . Не все программы генерируют вывод. Например, команда переименования файла (называемая по-разному mv , move или ren ) не выдает никаких сообщений об успешном завершении.
Если не перенаправлено , стандартный вывод наследуется от родительского процесса. В случае интерактивной оболочки это обычно текстовый терминал , который инициировал программу.
Дескриптор файла для стандартного вывода — 1 (один); определение POSIX <unistd.h>
— STDOUT_FILENO
; соответствующая <stdio.h>
переменная C — FILE* stdout
; аналогично, переменная C++ <iostream>
— std::cout
.
Стандартная ошибка — это другой выходной поток, который обычно используется программами для вывода сообщений об ошибках или диагностики. Это поток, независимый от стандартного вывода, и его можно перенаправить отдельно.
Это решает проблему полупредиката , позволяя различать вывод и ошибки, и аналогично функции, возвращающей пару значений – см. Проблема полупредиката: Многозначный возврат . Обычным местом назначения является текстовый терминал , который запустил программу, чтобы обеспечить наилучшие шансы быть увиденным, даже если стандартный вывод перенаправлен (поэтому нелегко наблюдать). Например, вывод программы в конвейере перенаправляется на ввод следующей программы или текстового файла, но ошибки из каждой программы по-прежнему поступают непосредственно в текстовый терминал, чтобы пользователь мог просматривать их в режиме реального времени. [2]
Допустимо и нормально направлять стандартный вывод и стандартную ошибку в одно и то же место назначения, например, на текстовый терминал. Сообщения появляются в том же порядке, в котором их записывает программа, если только не задействована буферизация . Например, в обычных ситуациях стандартный поток ошибок не буферизуется, но стандартный поток вывода буферизуется построчно; в этом случае текст, записанный в стандартную ошибку позже, может появиться на терминале раньше, если буфер стандартного потока вывода еще не заполнен.
Дескриптор файла для стандартной ошибки определен POSIX как 2 (два); заголовочный файл <unistd.h> предоставляет символ STDERR_FILENO
; [3] соответствующая <stdio.h>
переменная C — FILE* stderr
. Стандартный заголовок C++ <iostream>
предоставляет две переменные, связанные с этим потоком: std::cerr
и std::clog
, причем первая небуферизована, а вторая использует тот же механизм буферизации, что и все другие потоки C++.
Оболочки в стиле Bourne позволяют перенаправлять стандартные ошибки в то же место назначения, куда направляется стандартный вывод, используя
2>&1
Оболочки в стиле csh позволяют перенаправлять стандартные ошибки в то же место назначения, куда направляется стандартный вывод, используя
>&
Стандартная ошибка была добавлена в Unix в 1970-х годах после того, как несколько бесполезных запусков фотонабора закончились тем, что сообщения об ошибках были набраны, а не отображены на терминале пользователя. [4]
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 ПРОГРАММА MAIN INTEGER NUMBER READ ( UNIT = 5 , * ) NUMBER WRITE ( UNIT = 6 , '(A,I3)' ) ' NUMBER IS: ' , NUMBER END
! Fortran 2003 пример программы main use iso_fortran_env неявный none целое :: число чтение ( единица = INPUT_UNIT , * ) число запись ( единица = OUTPUT_UNIT , '(a,i3)' ) 'Число равно: ' , число конец программы
ALGOL 60 критиковали за отсутствие стандартного доступа к файлам. [ необходима цитата ]
Входные и выходные средства ALGOL 68 совместно назывались transput. [5] Костер координировал определение стандарта transput . Модель включала три стандартных канала: stand in
, stand out
, и stand back
.
В языке программирования C стандартные потоки ввода, вывода и ошибок присоединены к существующим файловым дескрипторам Unix 0, 1 и 2 соответственно. [6] В среде POSIX вместо магических чисел следует использовать определения < unistd.h > STDIN_FILENO , STDOUT_FILENO или STDERR_FILENO . Также предусмотрены указатели файлов stdin , stdout и stderr .
Кен Томпсон (разработчик и разработчик оригинальной операционной системы Unix) модифицировал sort в версии 5 Unix , чтобы принять "-" как представление стандартного ввода, что распространилось на другие утилиты и стало частью операционной системы как специальный файл в версии 8. Диагностика была частью стандартного вывода до версии 6 , после чего Деннис М. Ритчи создал концепцию стандартной ошибки. [7]
В Java стандартные потоки обозначаются как System.in
(для stdin), System.out
(для stdout) и System.err
(для stderr). [8]
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 ) ; } catch ( Exception e ) { System.err.println ( " Ошибка : " + e.getMessage ( ) ) ; } }
В C# и других языках .NET стандартные потоки обозначаются как System.Console.In
(для stdin), System.Console.Out
(для stdout) и System.Console.Error
(для stderr). [9] Базовые возможности чтения и записи для потоков 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# public static int Main ( string [ ] args ) { try { string s = System.Console.In.ReadLine ( ) ; double number = double.Parse ( s ) ; System.Console.Out.WriteLine ( " Число равно : { 0 : F3 } " , number ) ; return 0 ; // Если Parse() выдал исключение } catch ( ArgumentNullException ) { System . Console . Error . WriteLine ( "Число не введено!" ); } catch ( FormatException ) { System . Console . Error . WriteLine ( "Указанное значение не является допустимым числом!" ); } catch ( OverflowException ) { System . Console . Error . WriteLine ( "Указанное число слишком велико!" ); } возврат - 1 ; }
' Пример Visual Basic .NETPublic Function Main ( ) As Integer Try Dim s As String = System.Console . [ In ] .ReadLine ( ) Dim number As Double = Double.Parse ( s ) System.Console.Out.WriteLine ( " Число равно : { 0 : F3 } " , number ) Возврат 0 ' Если Parse() выдал исключение Catch ex As System . ArgumentNullException System . Console . [ Error ] . WriteLine ( "Число не введено!" ) Catch ex2 As System . FormatException System . Console . [ Error ] . WriteLine ( "Указанное значение не является допустимым числом!" ) Catch ex3 As System . OverflowException System . Console . [ Error ] . WriteLine ( "Указанное число слишком велико!" ) End Try Возврат - 1 Конечная функция
При применении System.Diagnostics.Process
класса можно использовать свойства StandardInput
экземпляра , StandardOutput
и StandardError
этого класса для доступа к стандартным потокам процесса.
Следующий пример, написанный на Python , показывает, как перенаправить стандартный ввод как в стандартный вывод, так и в текстовый файл.
#!/usr/bin/env питонимпортировать систему# Сохраняем текущий stdout, чтобы можно было вернуть sys.stdout# после того как мы завершим наше перенаправлениеstdin_fileno = sys . stdinstdout_fileno = sys . stdout# Перенаправить sys.stdout в файлsys.stdout = открыть ( " myfile.txt" , "w " ) ctr = 0для inps в stdin_fileno : ctrs = str ( ctr ) # Выводит на перенаправленный stdout () sys . stdout . write ( ctrs + ") это перенаправлено --->" + inps + " \n " ) # Выводит на экран фактически сохраненный обработчик stdout stdout_fileno . write ( ctrs + ") это в фактическое --->" + inps + " \n " ) ctr = ctr + 1# Закрыть файлsys.stdout.close ( )# Восстановить sys.stdout в наш старый сохраненный обработчик файловsys . stdout = stdout_fileno
Графические пользовательские интерфейсы (GUI) не всегда используют стандартные потоки; они это делают, когда GUI являются оболочками базовых скриптов и/или консольных программ, например, графический интерфейс менеджера пакетов Synaptic , который оборачивает команды apt в Debian и/или Ubuntu. GUI, созданные с помощью инструментов скриптования, таких как Zenity и KDialog проекта KDE [10], используют stdin, stdout и stderr и основаны на простых скриптах, а не на полном GUI, запрограммированном и скомпилированном на C/C++ с использованием Qt , GTK или другой эквивалентной фирменной структуры виджетов.
Меню Services , реализованное в NeXTSTEP и Mac OS X , также аналогично стандартным потокам. В этих операционных системах графические приложения могут предоставлять функциональность через общесистемное меню, которое работает с текущим выбором в GUI, независимо от того, в каком приложении.
Некоторые программы GUI, в основном на Unix, все еще записывают отладочную информацию в стандартный поток ошибок. Другие (например, многие медиаплееры Unix) могут читать файлы из стандартного ввода. Популярные программы Windows, которые открывают отдельное консольное окно в дополнение к своим окнам GUI, — это эмуляторы pSX и DOSBox .
GTK-сервер может использовать stdin в качестве интерфейса связи с интерпретируемой программой для реализации графического интерфейса пользователя.
Парадигма Common Lisp Interface Manager «представляет» элементы графического интерфейса, отправленные в расширенный выходной поток.