Стандартные потоки
В компьютерном программировании стандартные потоки представляют собой предварительно соединенные входные и выходные каналы связи. [ 1 ] между компьютерной программой и ее средой в момент начала ее выполнения. Три соединения ввода/вывода (I/O) называются стандартным вводом ( stdin ), стандартным выводом ( stdout ) и стандартной ошибкой ( stderr ). Первоначально ввод-вывод осуществлялся через физически подключенную системную консоль (ввод через клавиатуру, вывод через монитор), но стандартные потоки абстрагируют это. Когда команда выполняется через интерактивную оболочку , потоки обычно подключаются к текстовому терминалу, на котором запущена оболочка, но их можно изменить с помощью перенаправления или конвейера . В более общем смысле дочерний процесс наследует стандартные потоки своего родительского процесса .
Приложение
[ редактировать ]Пользователи обычно знают стандартные потоки как каналы ввода и вывода, которые обрабатывают данные, поступающие от устройства ввода, или записывают данные из приложения. Данные могут быть текстовыми с любой кодировкой или двоичными данными . Когда программа запускается как демон , ее стандартный поток ошибок перенаправляется в файл журнала, обычно для целей анализа ошибок.
Потоки могут использоваться для объединения приложений в цепочку, а это означает, что выходной поток одной программы может быть перенаправлен в качестве входного потока в другое приложение. Во многих операционных системах это выражается перечислением имен приложений, разделенных вертикальной чертой, которую по этой причине часто называют символом конвейера . Хорошо известным примером является использование приложения нумерации страниц , такого как more , предоставляющего пользователю контроль над отображением выходного потока на дисплее.
Фон
[ редактировать ]В большинстве операционных систем, предшествовавших Unix , программам приходилось явно подключаться к соответствующим устройствам ввода и вывода. Сложности, специфичные для ОС, сделали эту задачу программирования утомительной. Во многих системах необходимо было получить контроль над настройками среды, получить доступ к локальной таблице файлов, определить предполагаемый набор данных и правильно обращаться с оборудованием в случае устройства чтения перфокарт , накопителя на магнитной ленте , дисковода , линейного принтера , перфоратора карт. или интерактивный терминал.
Одним из нескольких революционных достижений Unix были абстрактные устройства , которые устранили необходимость для программы знать или заботиться о том, с какими устройствами она взаимодействует. [ нужна ссылка ] . Старые операционные системы навязывали программисту структуру записи и часто неортогональную семантику данных и управление устройством. Unix устранил эту сложность с помощью концепции потока данных: упорядоченной последовательности байтов данных, которую можно прочитать до конца файла . Программа также может записывать байты по своему желанию и в этом нет необходимости, и не может легко объявить их количество или группировку.
Еще одним прорывом в Unix стало автоматическое связывание ввода и вывода с клавиатурой и дисплеем терминала соответственно по умолчанию. [ нужна ссылка ] — программа (и программист) не сделала абсолютно ничего для установления ввода и вывода для типичной программы ввода-обработки-вывода (если только она не выбрала другую парадигму). Напротив, предыдущие операционные системы обычно требовали некоторого — часто сложного — языка управления заданиями для установления соединений, или эквивалентная нагрузка должна была быть организована программой. [ нужна ссылка ]
Поскольку Unix предоставлял стандартные потоки, среда выполнения Unix C также была обязана их поддерживать. В результате большинство сред выполнения C (и его потомков ), независимо от операционной системы, предоставляют эквивалентную функциональность.
Стандартный ввод (stdin)
[ редактировать ]Стандартный ввод — это поток, из которого программа считывает входные данные. Программа запрашивает передачу данных с помощью операции чтения . Не все программы требуют потокового ввода. Например, программы dir и ls (которые отображают имена файлов, содержащихся в каталоге) могут принимать аргументы командной строки , но выполнять свои операции без ввода потоковых данных.
Если не перенаправлено , стандартный ввод наследуется от родительского процесса. В случае интерактивной оболочки это обычно связано с устройством ввода терминала ( или псевдотерминала пользователя ), который в конечном итоге связан с клавиатурой .
В POSIX системах файловый дескриптор для стандартного ввода равен 0 (ноль); POSIX <unistd.h>
определение STDIN_FILENO
; соответствующий C <stdio.h>
абстракция обеспечивается через FILE* stdin
глобальная переменная. Аналогично, глобальный C++ std::cin
переменная типа <iostream>
обеспечивает абстракцию через потоки C++ . Подобные абстракции существуют в стандартных библиотеках ввода-вывода практически каждого языка программирования .
Стандартный вывод (stdout)
[ редактировать ]Стандартный вывод — это поток, в который программа записывает выходные данные. Программа запрашивает передачу данных при операции записи . Не все программы генерируют выходные данные. Например, команда переименования файла (также называемая mv , move или ren ) не сообщает об успехе.
Если не перенаправлено , стандартный вывод наследуется от родительского процесса. В случае интерактивной оболочки это обычно текстовый терминал , который инициировал программу.
Дескриптор файла для стандартного вывода равен 1 (один); POSIX <unistd.h>
определение STDOUT_FILENO
; соответствующий C <stdio.h>
переменная FILE* stdout
; аналогично, C++ <iostream>
переменная std::cout
.
Стандартная ошибка (stderr)
[ редактировать ]Стандартная ошибка — это еще один поток вывода, обычно используемый программами для вывода сообщений об ошибках или диагностики. Это поток, независимый от стандартного вывода, и его можно перенаправить отдельно.
Это решает проблему полупредикатов , позволяя различать выходные данные и ошибки, и аналогично функции, возвращающей пару значений — см. Проблема полупредикатов: многозначный возврат . Обычным пунктом назначения является текстовый терминал , который запустил программу, чтобы обеспечить наилучшие шансы на то, что ее увидят, даже если стандартный вывод перенаправлен (поэтому его нелегко наблюдать). Например, вывод программы в конвейере перенаправляется на ввод следующей программы или в текстовый файл, но ошибки каждой программы по-прежнему поступают непосредственно на текстовый терминал, поэтому пользователь может просмотреть их в режиме реального времени. [ 2 ]
Допустимо и нормально направлять стандартный вывод и стандартную ошибку в одно и то же место назначения, например, в текстовый терминал. Сообщения появляются в том же порядке, в котором их записывает программа, если не буферизация используется . Например, в обычных ситуациях стандартный поток ошибок не буферизуется, но стандартный поток вывода буферизуется по строкам; в этом случае текст, записанный в стандартную ошибку позже, может появиться на терминале раньше, если буфер стандартного потока вывода еще не заполнен.
Дескриптор файла для стандартной ошибки определяется POSIX как 2 (два); файл заголовка <unistd.h> содержит символ STDERR_FILENO
; [ 3 ] соответствующий C <stdio.h>
переменная FILE* stderr
. С++ <iostream>
стандартный заголовок предоставляет две переменные, связанные с этим потоком: std::cerr
и std::clog
, первый из которых не буферизуется, а второй использует тот же механизм буферизации, что и все остальные потоки C++.
Bourne Оболочки в стиле стандартные ошибки позволяют перенаправлять в тот же пункт назначения, куда направляется стандартный вывод, используя
2>&1
csh Оболочки в стиле стандартные ошибки позволяют перенаправлять в тот же пункт назначения, куда направляется стандартный вывод, используя
>&
Стандартная ошибка была добавлена в Unix в 1970-х годах после того, как несколько напрасных прогонов фотонабора закончились набором сообщений об ошибках, а не отображением на пользовательском терминале. [ 4 ]
Хронология
[ редактировать ]1950-е: Фортран
[ редактировать ]Фортран имеет эквивалент файловых дескрипторов Unix: по соглашению, многие реализации Фортрана используют номера единиц. UNIT=5
для стандартного ввода, UNIT=6
для стандартного вывода и UNIT=0
для stderr. В Фортране-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
[ редактировать ]АЛГОЛ 60 критиковали за отсутствие стандартного доступа к файлам. [ нужна ссылка ]
1968: АЛГОЛ 68
[ редактировать ]Средства ввода и вывода Алгола 68 вместе назывались транспутом. [ 5 ] Костер координировал определение стандарта транспортировки . Модель включала в себя три стандартных канала: 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 соответственно. [ 6 ] В POSIX среде < unistd.h > следует использовать определения STDIN_FILENO , STDOUT_FILENO или STDERR_FILENO вместо магических чисел . указатели файлов stdin , stdout и stderr Также предоставляются .
Кен Томпсон (разработчик и разработчик исходной операционной системы Unix) изменил сортировку в Unix версии 5, чтобы принять «-» как обозначение стандартного ввода, который распространился на другие утилиты и стал частью операционной системы как специальный файл в версии 8 . Диагностика была частью стандартного вывода до версии 6 , после чего Деннис М. Ритчи создал концепцию стандартной ошибки. [ 7 ]
1995: Ява
[ редактировать ]В Java стандартные потоки называются System.in
(для стандартного ввода), System.out
(для стандартного вывода) и 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 is:" + number);
} catch (Exception e) {
System.err.println("Error:" + e.getMessage());
}
}
2000-е: .NET
[ редактировать ]В C# и других языках .NET стандартные потоки называются System.Console.In
(для стандартного ввода), System.Console.Out
(для стандартного вывода) и 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
(стандартный ввод) и 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 -: Питон (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) не всегда используют стандартные потоки; они делают, когда графические интерфейсы являются оболочками базовых сценариев и/или консольных программ, например графический интерфейс менеджера пакетов Synaptic , который обертывает apt-команды в Debian и/или Ubuntu. Графические интерфейсы, созданные с помощью инструментов сценариев, таких как Zenity и KDialog, в рамках KDE. проекта [ 10 ] используют stdin, stdout и stderr и основаны на простых сценариях, а не на полноценном графическом интерфейсе, запрограммированном и скомпилированном на C/C++ с использованием Qt , GTK или другой эквивалентной собственной платформы виджетов.
Меню Services , реализованное в NeXTSTEP и Mac OS X , также аналогично стандартным потокам. В этих операционных системах графические приложения могут обеспечивать функциональность через общесистемное меню, которое работает с текущим выбором в графическом интерфейсе, независимо от того, в каком приложении.
Некоторые программы с графическим пользовательским интерфейсом, в основном в Unix, по-прежнему записывают отладочную информацию в стандартную ошибку. Другие (например, многие медиаплееры Unix) могут читать файлы со стандартного ввода. Популярными программами для Windows, открывающими отдельное окно консоли в дополнение к окнам с графическим интерфейсом, являются эмуляторы pSX и DOSBox .
GTK-сервер может использовать стандартный ввод в качестве интерфейса связи с интерпретируемой программой для реализации графического интерфейса.
Парадигма Common Lisp Interface Manager «представляет» элементы графического интерфейса, отправляемые в расширенный поток вывода.
См. также
[ редактировать ]- Перенаправление (вычисления)
- Поток (вычисления)
- Ввод/вывод
- Ввод/вывод файла C
- СИСИН и СИСВУТ
- Стандартные потоки в OpenVMS
Ссылки
[ редактировать ]- ^ Д. М. Ричи, «Система потокового ввода-вывода» , Технический журнал AT&T Bell Laboratories, 68 (8), октябрь 1984 г.
- ^ «Что такое stdin, stdout и stderr в Linux? | CodePre.com» . 2 декабря 2021 г. Проверено 8 апреля 2022 г.
- ^ "<unistd.h>" . Базовые спецификации открытой группы, выпуск 6 — стандарт IEEE 1003.1, издание 2004 г. Открытая группа. 2004.
- ^ Джонсон, Стив (11 декабря 2013 г.). «[TUHS] Фотонаборная машина Graphic Systems C/A/T» (список рассылки). Архивировано из оригинала 25 сентября 2020 г. Проверено 07.11.2020 .
- ^ « Пересмотренный отчет об алгоритмическом языке Algol 68 », под редакцией А. ван Вейнгаардена, Б. Дж. Майу, Дж. Э. Пека, Ч. А. Костера, М. Синцова, К. Х. Линдси, LGLT Meertens и RG Fisker, Раздел 10.3.
- ^ «Stdin(3): Стандартные потоки ввода-вывода — справочная страница Linux» . сайт die.net . Архивировано из оригинала 8 июня 2023 г.
- ^ Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Лаборатории Белла. 139. Архивировано (PDF) из оригинала 15 декабря 2023 г.
- ^ «Система (Платформа Java SE 7)» . Справочный центр Oracle . Проверено 20 июля 2012 г.
- ^ «.NET Framework 4.7.1, mscorlib, console.cs» . Справочный источник — Microsoft . Архивировано из оригинала 10 декабря 2017 года . Проверено 10 декабря 2017 г.
- ^ Кисслинг, Кристиан (2009). «Добавление графических элементов в ваши скрипты с помощью Zenity и KDialog» . Журнал Линукс . Проверено 11 апреля 2021 г.
Источники
[ редактировать ]- « Стандартные потоки », Библиотека GNU C.
- Справочное руководство KRONOS 2.1 , Control Data Corporation, номер детали 60407000, 1974 г.
- NOS версии 1 Application Programmer's Instant , Control Data Corporation, номер детали 60436000, 1978 г.
- Уровень 68. Введение в программирование на MULTICS. Архивировано 25 февраля 2021 г. в Wayback Machine , Honeywell Corporation, 1981 г.
- Эволюция операционной системы MVS , корпорация IBM, 1981 г.
- Комментарий Львов к шестому изданию UNIX , Джон Лайонс, ISBN 1-57398-013-7 , 1977 г.
- Класс консоли, библиотека классов .NET Framework , корпорация Microsoft, 2008 г.
Внешние ссылки
[ редактировать ]- Определение стандартного ввода — The Linux Information Project
- Определение стандартного вывода - Информационный проект Linux
- Стандартное определение ошибки - Информационный проект Linux