Стандартные потоки ввода/вывода
Стандартные потоки ввода и вывода в UNIX/Linux наряду с файлами являются одним из наиболее распространённых средств для обмена информацией процессов с внешним миром, а перенаправления >, >> и |, одной из самых популярных конструкций командного интерпретатора.
На этой странице рассматриваются как базовые вопросы использования потоков ввода/вывода, так и тонкости и хитрости, например, почему не работает echo text | read ver и многие другие.
[править] Потоки и файлы
Процесс взаимодействия с пользователем выполняется в терминах записи и чтения в файл. То есть вывод на экран представляется как запись в файл, а ввод — как чтение файла. Файл, из которого осуществляется чтение, называется стандартным потоком ввода, а в который осуществляется запись — стандартным потоком вывода.

Стандартные потоки — воображаемые файлы, позволяющие осуществлять взаимодействие с пользователем как чтение и запись в файл. Кроме потоков ввода и вывода, существует еще и стандартный поток ошибок, на который выводятся все сообщения об ошибках и те информативные сообщения о ходе работы программы, которые не могут быть выведены в стандартный поток вывода.
Стандартные потоки привязаны к файловым дескрипторам с номерами 0, 1 и 2.
- Стандартный поток ввода (stdin) — 0;
- Стандартный поток вывода (stdout) — 1;
- Стандартный поток ошибок (stderr) — 2.
Вывод данных на экран и чтение их с клавиатуры происходит потому, что по умолчанию стандартные потоки ассоциированы с терминалом пользователя. Это не является обязательным — потоки можно подключать к чему угодно — к файлам, программам и даже устройствам. В командном интерпретаторе bash такая операция называется перенаправлением.
< файл Использовать файл как источник данных для стандартного потока ввода. >файл Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху. 2> файл Направить стандартный поток ошибок в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху. >>файл Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — данные будут дописаны к нему в конец. 2>>файл Направить стандартный поток ошибок в файл. Если файл не существует, он будет создан; если существует — данные будут дописаны к нему в конец. &>файл или >&файл Направить стандартный поток вывода и стандартный поток ошибок в файл. Другая форма записи: >файл 2>&1. >&- Закрыть поток вывода перед вызовом команды (спасибо [1]); 2>&- Закрыть поток ошибок перед вызовом команды (спасибо [2]); cat
Весь текст между блоками EOF (в общем случае вместо EOF можно использовать любое слово) будет выведен на экран. Важно: перед последним EOF не должно быть пробелов! (heredoc синтаксис).
Пример. Эта команда объединяет три файла: header, body и footer в один файл letter:
%$ cat header body footer > letter
Команда cat по очереди выводит содержимое файлов, перечисленных в качестве параметров на стандартный поток вывода. Стандартный поток вывода перенаправлен в файл letter.
Здесь используется сразу перенаправление стандартного потока ввода и стандартного потока вывода:
%$ sort < unsortedlines >sortedlines
Программа sort сортирует данные, поступившие в стандартный поток ввода, и выводит их на стандартный поток вывода. Стандартный поток ввода подключен к файлу unsortedlines, а выход записывается в sortedlines.
Здесь перенаправлены потоки вывода и ошибок:
%$ find /home -name '*.rpm' >rpmlist 2> /dev/null
Программа find ищет в каталоге /home файлы с суффиксом .rpm. Список найденных файлов записывается в файл rpmlist. Все сообщения об ошибках удаляются. Удаление достигается при помощи перенаправления потока ошибок на устройство /dev/null — специальный файл, означающий ничто. Данные, отправленные туда, безвозвратно исчезают. Если же прочитать содержимое этого файла, он окажется пуст.
Для того чтобы лучше понять, что потоки работают как файлы, рассмотрим такой пример:
%$ cat > /tmp/fff & [1] 28378 [1]+ Stopped cat > /tmp/fff %$ ls -l /proc/28378/fd/ total 0 lrwx------ 1 igor igor 64 2009-06-24 18:58 0 -> /dev/pts/1 l-wx------ 1 igor igor 64 2009-06-24 18:58 1 -> /tmp/fff lrwx------ 1 igor igor 64 2009-06-24 18:58 2 -> /dev/pts/1 l-wx------ 1 igor igor 64 2009-06-24 18:58 5 -> pipe:[13325] lr-x------ 1 igor igor 64 2009-06-24 18:58 7 -> pipe:[13329]
Программа cat запускается для записи данных в файл /tmp/fff. Он запускается в фоне (&), и получает номер работы 1 ([1]). Процесс этой программы имеет номер 28378.
Информация о процессе 28738 находится в каталоге /proc/28738 специальной псевдофайловой системы /proc. В частности, в подкаталоге /proc/28738/fd/ находится список файловых дескрипторов для открытых процессом файлов.
Здесь видно, что стандартный поток ввода (0), и стандартный поток ошибок (2) процесса подключены на терминал, а вот стандартный поток вывода (1) перенаправлен в файл.
Завершить работу программы cat можно командой kill %1.
Командный интерпретатор — это тоже процесс. И у него есть стандартные потоки ввода и вывода. Если интерпретатор работает в интерактивном режиме, то они подключены на консоль (вывода на экран; чтение с клавиатуры). Можно обратиться напрямую к этим потокам изнутри интерпретатора:
- /dev/stdin — стандартный поток ввода;
- /dev/stdout — стандартный поток вывода;
- /dev/stderr — стандартный поток ошибок.
Например, здесь видно, что потоки ссылаются в конечном итоге на файл-устройство терминала, с которым работает интерпретатор:
%$ ls -l /dev/std* lrwxrwxrwx 1 root root 15 2009-06-17 23:54 /dev/stderr -> /proc/self/fd/2 lrwxrwxrwx 1 root root 15 2009-06-17 23:54 /dev/stdin -> /proc/self/fd/0 lrwxrwxrwx 1 root root 15 2009-06-17 23:54 /dev/stdout -> /proc/self/fd/1 %$ ls -l /proc/self/fd/[012] lrwx------ 1 igor igor 64 2009-06-24 18:16 /proc/self/fd/0 -> /dev/pts/1 lrwx------ 1 igor igor 64 2009-06-24 18:16 /proc/self/fd/1 -> /dev/pts/1 lrwx------ 1 igor igor 64 2009-06-24 18:16 /proc/self/fd/2 -> /dev/pts/1 %$ tty /dev/pts/1
[править] Каналы
Стандартные потоки можно перенаправлять не только в файлы, но и на вход других программ. Если поток вывода одной программы соединить с потоком ввода другой программы, получится конструкция, называемая каналом, конвейером или пайпом (от англ. pipe, труба).

В bash канал выглядит как последовательность команд, отделенных друг от друга символом |:
команда1 | команда2 | команда3 .
Стандартный поток вывода команды1 подключается к стандартному потоку ввода команды2, стандартный поток вывода команды2 в свою очередь подключается к потоку ввода команды3 и т.д.
В UNIX/Linux существует целый класс команд, предназначенных для преобразования потоков данных в каналах. Такие программы известны как фильтры. Программа-фильтр читает данные, поступающие со стандартного потока ввода (на вход), преобразовывает их требуемым образом и выводит на стандартный поток вывода (на выход). Существует множество хорошо известных фильтров, призванных решать определенные задачи, и являющихся незаменимым инструментом в руках пользователя ОС.
Каналы в ОС Linux являются одной из наиболее часто применяемых конструкций, а фильтры — наиболее часто применяемых программ. Большинство повседневных задач в Linux легко решаются при помощи конструкций построенных на основе нескольких фильтров.
Программы, образующие канал, выполняются параллельно как независимые процессы.
Можно создавать ответвление в каналах. Команда tee позволяет сохранять данные, передающиеся в канале:
tee [опции] файл
Программа tee копирует данные, поступающие на стандартный поток ввода, в указанные в качестве аргументов команды файлы, и передает данные на стандартный поток вывода.
Рассмотренный ниже пример: сортируется файл unsortedlines и результат записывается в sortedlines.
%$ cat unsortedlines | sort > sortedlines
Команда выполняет те же действия, но запись является более наглядной.
Вот пример посложнее. Вывести название и размер пользовательского каталога, занимающее наибольшее место на диске.
$ du -s /home/* | sort -nr | head -1
Программа du, при вызове ее с ключом -s, сообщает суммарный объем каждого каталога или файла, перечисленного в ее параметрах.
Ключ -n команды sort означает, что сортировка должна быть арифметической, т.е. строки должны рассматриваться как числа, а не как последовательности символов (Например, 12>5 в то время как строка ’12’-r означает изменения порядка сортировки — с возрастающего на убывающий.
Команда head выводит несколько первых строк поступающего на ее вход потока, отбрасывая все остальные. Ключ -1 означает, что надо вывести только одну строку.
Таким образом, список пользовательских каталогов с их суммарным объемом арифметически сортируется по убыванию, и из полученного списка берется первая строка, т.е. строка с наибольшим числом, соответствующая самому объемному каталогу.
Использование команды tee:
$ sort text | tee sorted_text | head -n 1
Содержимое файла text сортируется, и результат сортировки записывается в файл sorted_text. Первая строка отсортированного текста выдается на экран.
[править] Программы фильтры
В UNIX/Linux существует целый класс команд, которые принимают данные со стандартного потока ввода, каким-то образом обрабатывают их, и выдают результат на стандартный поток вывода. Такие программы называются программами-фильтрами.
Как правило, все эти программы работают как фильтры, если у них нет аргументов (опции могут быть), но как только им в качестве аргумента передаётся файл, они считывают данные из этого файла, а не со стандартного потока ввода (существуют и исключения, например, программа tr, которая обрабатывает данные поступающие исключительно через стандартный поток ввода).

cat Считывает данные со стандартного потока ввода и передаёт их на стандартный поток вывода. Без опций работает как простой повторитель. С опциями может фильтровать пустые строки, нумеровать строки и делать другую подобную работу. head Показывает первые 10 строк (или другое заданное количество), считанных со стандартного потока ввода. tail Показывает последние 10 строк (или другое заданное количество), считанные со стандартного потока ввода. Важный частный случай tail -f, который в режиме слежения показывает концовку файла. Это используется, в частности, для просмотра файлов журнальных сообщений. cut Вырезает столбец (по символам или полям) из потока ввода и передаёт на поток вывода. В качестве разделителей полей могут использоваться любые символы. sort Отсортировать данные в соответствии с какими-либо критериями, например, арифметически по второму столбцу. uniq Удалить повторяющиеся строки. Или (с ключом -с) не просто удалить, а написать сколько таких строк было. Учитываются только подряд идущие одинаковые строки, поэтому часто данные сортируются перед тем как отправить их на вход программе. tee Ответвить данные в файл. Используется для сохранения промежуточных данных, передающихся в потоке, в файл. bc Вычислить каждую отдельную строку потока и записать вместо неё результат вычисления. hexdump Показать шестнадцатеричное представление данных, поступающих на стандартный поток ввода. strings вычленить и показать в стандартном потоке (или файле) то, что напоминает строки. Всё что не похоже на строковые последовательности, игнорировать. Полезна в сочетании с grep для поиска интересующих строковых последовательностей в бинарных файлах. grep Отфильтровать поток, и показать только строки, содержащие (или не содержащие) заданное регулярное выражение. tr Посимвольная замена текста в потоке. Например, tr A-Z a-z меняет регистр символов с большого на маленький. sed Обработать текст в соответствии с заданным скриптом. Наиболее часто используется для замены текста в потоке: sed s/было/стало/g awk Обработать текст в соответствии с заданным скриптом. Как правило, используется для обработки текстовых таблиц, например таких как вывод ps aux и тому подобных, но не только. perl Обработать текст в соответствии с заданным скриптом. Возможности языка Perl выходят далеко за рамки однострочников для командной строки, но с однострочниками он справляется особенно виртуозно. В Perl существует оператор <> (diamond operator) и конструкция while(<>) < . >, которая предполагает обработку данных со стандартного потока ввода (или из файлов, если они переданы в качестве аргументов). При написании однострочников можно использовать ключи -n (равносильный оборачиванию кода в while(<>) < . >) или -p (равносильный while(<>) < . >).

sh -s Текст, который передаётся на стандартный поток ввода sh -s может интерпретироваться как последовательность команд shell. На выход передаётся результат их исполнения. ssh Средство удалённого доступа ssh, может работать как фильтр. ssh подхватывает данные, переданные ему на стандартный поток ввода, передаёт их на удалённых хост и подаёт на вход процессу программы, имя которой было передано ему в качестве аргумента. Результат выполнения программы (то есть то, что она выдала на стандартный поток вывода) передаётся со стандартного вывода ssh.
[править] Переменные командного интерпретатора и потоки
Для того чтобы вывести содержимое переменной командного интерпретатора на стандартный поток вывода, используется команда echo:
%$ echo $VAR
На стандартный поток ошибок данные можно передать с помощью перенаправления:
%$ echo $VAR > /dev/stderr
Содержимое переменной (или любой другой текст) поступят не на стандартный поток вывода, а на стандартный поток ошибок.
Считать данные со стандартного потока ввода внутрь одной или нескольких переменных можно при помощи команды read:
%$ read VAR
Строка из стандартного потока ввода считается внутрь переменной VAR.
Если указать несколько переменных, то в первую попадёт первое слово; во вторую — второе слово; в последнюю — всё остальное.
%$ df -h | head -1 Filesystem Size Used Avail Use% Mounted on %$ df -h | head -1 | < read VAR1 VAR2 VAR3; echo $VAR1; echo $VAR2; echo $VAR3 ; >Filesystem Size Used Avail Use% Mounted on
Обратите внимание на конструкцию read VAR; echo $VAR >. Переменная считанная из канала с помощью read будет доступна только внутри < >. Например echo text | read var; echo $var выведет пустое место. Это связано с тем, что для перенаправления внутрь read shell порождает дочерний процесс, в котором и исполняет read. Переменная дочернего процесса не передаётся наружу. (Внимание. В zsh всё работает и без этих костылей).
Если прочитать данные со стандартного потока ввода не удалось, то команда read возвращает код завершения отличный от нуля. Это позволяет использовать read, например, в такой конструкции:
%$ cat users | while read user do useradd $user done
В этом примере read считывает строки из файла users, и для каждой прочитанной строки вызывается команда useradd, которая добавляет пользователя в системе. В результате: создаются учётные записи пользователей, имена которых перечислены в файле users.
Переменная user после выхода из цикла остаётся в том же виде, в каком она была до входа в цикл (а не содержит последнее значение файла, как можно было бы предположить). Это связано с тем, что для обработки while, на вход которому направлен канал, порождается дочерний интерпретатор, и модификация переменной происходит внутри него.
[править] Именованные каналы
Безымянный канал можно построить только между процессами, которые порождены от одного процесса (и на практике они должны быть порождены одновременно, а не последовательно, хотя теоретически это не обязательно). Если же процессы имеют разных родителей, то между ними обычный, безымянный канал построить не получится.

Например, в данном случае d и e, и f и g легко могут быть соединены при помощи канала, но e и f соединить с помощью канала не получится.
Для решения этой задачи используются именованные каналы fifo (first in, first out). Они во всём повторяют обычные каналы (pipe), только имеют привязку к файловой системе. Создать именованный канал можно командой mkfifo:
%$ mkfifo /tmp/fifo
Созданный канал можно использовать для соединения процессов между собой. Например, эти перенаправления будут работать одинаково:
%$ f | g
%$ f > /tmp/fifo & g < /tmp/fifo
(здесь f и g — процессы из вышеуказанной иерархии процессов). Процессы f и g имеют общего предка. А вот для процессов e и g, не связанных между собой, обычный канал использовать не получится, только именованный:
%$ e > /tmp/fifo& %$ g < /tmp/fifo # в другом интерпретаторе
[править] Потоки ввода/вывода и терминал
Большинство программ, которые работают с потоками ввода и вывода, работают с ними как с простыми файлами, и не рассчитывают на то, что поток подключен к терминалу. Но не все. Если потоки ввода/вывода отключаются от терминала и перенаправляются в файл, часть возможностей программы может пропасть.
Например, если командный интерпретатор отвязать от терминала, то у него потеряется множество интерактивных возможностей:
%$ cat | sh -i | cat
Например, возможности прокручивать историю команд у него теперь нет. Возможности по редактированию теперь тоже сильно урезаны. Фактически, редактирование команды теперь выполняется уже с помощью программы cat, которая держит терминал, а интерпретатору поступают уже полностью введённые команды.
Проверить, подключен ли наш стандартный поток к терминалу, или он перенаправлен в файл, можно при помощи test, ключ -t:
%$ test -t 0 && echo terminal terminal %$ cat | test -t 0 && echo terminal %$ cat | test -t 0 || echo file file
[править] Подстановка процесса
Есть хитрый трюк, который в чистом виде перенаправлением потока ввода/вывода не является, но имеет к нему отношение — подстановка процесса. Результат выполнения процесса можно представить в виде воображаемого файла и передать его другому процессу.
команда1При таком вызове процессу команда1 передаётся файл (созданный налету канал или файл /dev/fd/. ), в котором находятся данные, которые выводит команда2.
Например, у вас есть два файла с различными словами по одному в строке. Вы хотите определить, какие из них встречаются в одном файле, но не встречаются во втором. И наоборот.
%$ cat f1 a b c b b %$ cat f2 a c c c %$ diff <(sort -u f1) <(sort -u f2) 2d1 < bПолучается, что в первом файле присутствует слово, которое отсутствует во втором (слово b).
[править] Перенаправление вывода скрипта
Потоки ввода/вывода скрипта, исполняющегося сейчас, изнутри самого скрипта можно следующим образом:
exec > file exec 2>&1
- How do I redirect the output of an entire shell script within the script itself?
[править] Поменять местами стандартный поток вывода и стандартный поток ошибок
$ cmd 3>&2 2>&1 1>&3
- IO Redirection - Swapping stdout and stderr (Advanced)
[править] Просмотр прогресса и скорости обработки данных в потоке
Если пропустить данные, передающиеся в канале, через программу pv, то будет видна скорость обработки, время в течение которого работает канал и, если известно сколько данных должно быть обработано, приблизительное время окончания выполнения.
$ pv /tmp/shre.tar.gz | tar xz 62MB 0:00:18 [12,6MB/s] [==> ] 10% ETA 0:02:27
[править] Дополнительная информация
- Monadic i/o and UNIX shell programming (англ.) — взгляд на каналы (pipelines) как на монады
- http://wiki.bash-hackers.org/howto/redirection_tutorial (англ.) — очень подробно на живых примерах разобраны различные виды перенаправлений
- How do I write stderr to a file while using “tee” with a pipe? — прекрасный пример использования подстановки процесса (process substitution); в этом примере таким образом перенаправляется поток ошибок
- http://mywiki.wooledge.org/BashGuide/InputAndOutput (англ.) — всевозможные манипуляции со стандартными потоками ввода и вывода
| Интерфейс командной строки | |
|---|---|
| Основы | Потоки ввода/вывода • Командная строка |
| Пользовательское окружение | Оболочка интерпретатора • Приглашение командного интерпретатора • bash_completion • shopt |
| Скриптинг | Скриптинг • Интерпретатор • Shebang • Shell-скриптинг • shell-framework • expect • awk • sed |
Потоки ввода-вывода. Работа с файлами
Отличительной чертой многих языков программирования является работа с файлами и потоками. В Java основной функционал работы с потоками сосредоточен в классах из пакета java.io .
Ключевым понятием здесь является понятие потока . Хотя понятие "поток" в программировании довольно перегружено и может обозначать множество различных концепций. В данном случае применительно к работе с файлами и вводом-выводом мы будем говорить о потоке (stream), как об абстракции, которая используется для чтения или записи информации (файлов, сокетов, текста консоли и т.д.).
Поток связан с реальным физическим устройством с помощью системы ввода-вывода Java. У нас может быть определен поток, который связан с файлом и через который мы можем вести чтение или запись файла. Это также может быть поток, связанный с сетевым сокетом, с помощью которого можно получить или отправить данные в сети. Все эти задачи: чтение и запись различных файлов, обмен информацией по сети, ввод-ввывод в консоли мы будем решать в Java с помощью потоков.
Объект, из которого можно считать данные, называется потоком ввода , а объект, в который можно записывать данные, - потоком вывода . Например, если надо считать содержание файла, то применяется поток ввода, а если надо записать в файл - то поток вывода.
В основе всех классов, управляющих потоками байтов, находятся два абстрактных класса: InputStream (представляющий потоки ввода) и OutputStream (представляющий потоки вывода)
Но поскольку работать с байтами не очень удобно, то для работы с потоками символов были добавлены абстрактные классы Reader (для чтения потоков символов) и Writer (для записи потоков символов).
Все остальные классы, работающие с потоками, являются наследниками этих абстрактных классов. Основные классы потоков:

Потоки байтов
Класс InputStream
Класс InputStream является базовым для всех классов, управляющих байтовыми потоками ввода. Рассмотрим его основные методы:
- int available() : возвращает количество байтов, доступных для чтения в потоке
- void close() : закрывает поток
- int read() : возвращает целочисленное представление следующего байта в потоке. Когда в потоке не останется доступных для чтения байтов, данный метод возвратит число -1
- int read(byte[] buffer) : считывает байты из потока в массив buffer. После чтения возвращает число считанных байтов. Если ни одного байта не было считано, то возвращается число -1
- int read(byte[] buffer, int offset, int length) : считывает некоторое количество байтов, равное length, из потока в массив buffer. При этом считанные байты помещаются в массиве, начиная со смещения offset, то есть с элемента buffer[offset] . Метод возвращает число успешно прочитанных байтов.
- long skip(long number) : пропускает в потоке при чтении некоторое количество байт, которое равно number
Класс OutputStream
Класс OutputStream является базовым классом для всех классов, которые работают с бинарными потоками записи. Свою функциональность он реализует через следующие методы:
- void close() : закрывает поток
- void flush() : очищает буфер вывода, записывая все его содержимое
- void write(int b) : записывает в выходной поток один байт, который представлен целочисленным параметром b
- void write(byte[] buffer) : записывает в выходной поток массив байтов buffer.
- void write(byte[] buffer, int offset, int length) : записывает в выходной поток некоторое число байтов, равное length , из массива buffer , начиная со смещения offset , то есть с элемента buffer[offset] .
Абстрактные классы Reader и Writer
Абстрактный класс Reader предоставляет функционал для чтения текстовой информации. Рассмотрим его основные методы:
- absract void close() : закрывает поток ввода
- int read() : возвращает целочисленное представление следующего символа в потоке. Если таких символов нет, и достигнут конец файла, то возвращается число -1
- int read(char[] buffer) : считывает в массив buffer из потока символы, количество которых равно длине массива buffer. Возвращает количество успешно считанных символов. При достижении конца файла возвращает -1
- int read(CharBuffer buffer) : считывает в объект CharBuffer из потока символы. Возвращает количество успешно считанных символов. При достижении конца файла возвращает -1
- absract int read(char[] buffer, int offset, int count) : считывает в массив buffer, начиная со смещения offset, из потока символы, количество которых равно count
- long skip(long count) : пропускает количество символов, равное count. Возвращает число успешно пропущенных символов
Класс Writer определяет функционал для всех символьных потоков вывода. Его основные методы:
- Writer append(char c) : добавляет в конец выходного потока символ c. Возвращает объект Writer
- Writer append(CharSequence chars) : добавляет в конец выходного потока набор символов chars. Возвращает объект Writer
- abstract void close() : закрывает поток
- abstract void flush() : очищает буферы потока
- void write(int c) : записывает в поток один символ, который имеет целочисленное представление
- void write(char[] buffer) : записывает в поток массив символов
- absract void write(char[] buffer, int off, int len) : записывает в поток только несколько символов из массива buffer. Причем количество символов равно len, а отбор символов из массива начинается с индекса off
- void write(String str) : записывает в поток строку
- void write(String str, int off, int len) : записывает в поток из строки некоторое количество символов, которое равно len, причем отбор символов из строки начинается с индекса off
Функционал, описанный классами Reader и Writer, наследуется непосредственно классами символьных потоков, в частности классами FileReader и FileWriter соответственно, предназначенными для работы с текстовыми файлами.
Теперь рассмотрим конкретные классы потоков.
Потоковый ввод-вывод
Эти функции обрабатывают данные различных размеров и форматов, — от одного символа до больших структур данных. Они также предоставляют возможность буферизации, которая может повысить производительность. Размер буфера потока по умолчанию составляет 4 КБ. Эти подпрограммы влияют только на буферы, созданные подпрограммами библиотеки времени выполнения, и не затрагивают буферы, созданные операционной системой.
Подпрограммы потокового ввода-вывода
| Маршрут | Использование |
|---|---|
| clearerr , clearerr_s | Очистка индикатора ошибки для потока |
| fclose | Закрытие потока |
| _fcloseall | Закрытие всех открытых потоков, кроме stdin , stdout и stderr |
| _fdopen , wfdopen | Связывание потока с дескриптором открытого файла |
| feof | Проверка файла или потока на предмет конца |
| ferror | Проверка на наличие ошибки в потоке |
| fflush | Сброс потока в буфер или на запоминающее устройство |
| fgetc , fgetwc | Считывание символа из потока (функциональные версии getc и getwc ) |
| _fgetchar , _fgetwchar | Считать символ из stdin (функциональные версии getchar и getwchar ) |
| fgetpos | Получение индикатора позиции потока |
| fgets , fgetws | Считывание строки из потока |
| _fileno | Получение дескриптора файла, связанного с потоком |
| _flushall | Сброс всех потоков в буфер или запоминающее устройство |
| fopen , _wfopen , fopen_s , _wfopen_s | Открытие потока |
| fprintf , _fprintf_l , fwprintf , _fwprintf_l , fprintf_s , _fprintf_s_l , fwprintf_s , _fwprintf_s_l | Запись форматированных данных в поток |
| fputc , fputwc | Запись символа в поток (функциональные версии putc и putwc ) |
| _fputchar , _fputwchar | Запись символа в stdout (функциональные версии putchar и putwchar ) |
| fputs , fputws | Запись строки в поток |
| fread | Считывание неформатированных данных из потока |
| freopen , _wfreopen , freopen_s , _wfreopen_s | Переназначение потокового указателя FILE , чтобы он указывал на новый файл или устройство |
| fscanf , fwscanf , fscanf_s , _fscanf_s_l , fwscanf_s , _fwscanf_s_l | Считывание форматированных данных из потока |
| fseek , _fseeki64 | Перемещение позиции в файле в заданное место |
| fsetpos | Задание индикатора позиции в потоке |
| _fsopen , _wfsopen | Открытие потока с совместным доступом к файлу |
| ftell , _ftelli64 | Получение текущей позиции в файле |
| fwrite | Запись неформатированных элементов данных в поток |
| getc , getwc | Считывание символа из потока (версии-макросы fgetc и fgetwc ) |
| getchar , getwchar | Считывание символа из stdin (версии-макросы fgetchar и fgetwchar ) |
| _getmaxstdio | Возвращает количество одновременно открытых файлов, допустимое на уровне потокового ввода-вывода. |
| gets_s , _getws_s | Считывание строки из stdin |
| _getw | Считывание двоичного числа int из потока |
| printf , _printf_l , wprintf , _wprintf_l , printf_s , _printf_s_l , wprintf_s , _wprintf_s_l | Запись форматированных данных в stdout |
| putc , putwc | Запись символа в поток (версии-макросы fputc и fputwc ) |
| putchar , putwchar | Запись символа в stdout (версии-макросы fputchar и fputwchar ) |
| puts , _putws | Запись строки в поток |
| _putw | Запись двоичного числа int в поток |
| rewind | Перемещение позиции в файле в начало потока |
| _rmtmp | Удаление временных файлов, созданных tmpfile |
| scanf , _scanf_l , wscanf , _wscanf_l , scanf_s , _scanf_s_l , wscanf_s , _wscanf_s_l | Считывание форматированных данных из stdin |
| setbuf | Управление потоковой буферизацией |
| _setmaxstdio | Задание максимального числа одновременно открытых файлов на уровне потокового ввода-вывода |
| setvbuf | Управление потоковой буферизацией и размером буфера |
| _snprintf , _snwprintf , _snprintf_s , _snprintf_s_l , _snwprintf_s , _snwprintf_s_l | Запись форматированных данных указанной длины в строку |
| _snscanf , _snwscanf , _snscanf_s , _snscanf_s_l , _snwscanf_s , _snwscanf_s_l | Считывают форматированные данные указанной длины из стандартного входного потока. |
| sprintf , swprintf , sprintf_s , _sprintf_s_l , swprintf_s , _swprintf_s_l | Запись форматированных данных в строку |
| sscanf , , swscanf sscanf_s _sscanf_s_l, swscanf_s _swscanf_s_l | Считывание форматированных данных из строки |
| _tempnam , _wtempnam | Создание временного имени файла в заданном каталоге |
| tmpfile , tmpfile_s | Создание временного файла |
| tmpnam , _wtmpnam , tmpnam_s , _wtmpnam_s | Создание временного имени файла |
| ungetc , ungetwc | Отправка символа обратно в поток |
| _vcprintf , _vcwprintf , _vcprintf_s , _vcprintf_s_l , _vcwprintf_s , _vcwprintf_s_l | Вывод форматированных данных на консоль |
| vfprintf , vfwprintf , vfprintf_s , _vfprintf_s_l , vfwprintf_s , _vfwprintf_s_l | Запись форматированных данных в поток |
| vprintf , vwprintf , vprintf_s , _vprintf_s_l , vwprintf_s , _vwprintf_s_l | Запись форматированных данных в stdout |
| _vsnprintf , _vsnwprintf , vsnprintf_s , _vsnprintf_s , _vsnprintf_s_l , _vsnwprintf_s , _vsnwprintf_s_l | Запись форматированных данных указанной длины в буфер |
| vsprintf , vswprintf , vsprintf_s , _vsprintf_s_l , vswprintf_s , _vswprintf_s_l | Запись форматированных данных в буфер |
Когда программа начинает выполнение, код запуска автоматически открывает несколько потоков: стандартный ввода (на который указывает stdin ), стандартный вывода (на который указывает stdout ) и стандартный вывода ошибок (на который указывает stderr ). Эти потоки по умолчанию направляются на консоль (клавиатуру и экран). С помощью freopen можно перенаправить stdin , stdout или stderr на файл на диске или на устройство.
Файлы, открытые с помощью потоковых подпрограмм, по умолчанию буферизуются. stderr Функции stdout удаляются всякий раз, когда они заполнены или, если вы записываете на символьное устройство после каждого вызова библиотеки. Если программа завершается аварийно, буферы вывода могут не быть сброшены, что приводит к потере данных. Используйте fflush или _flushall убедитесь, что буфер, связанный с указанным файлом, удаляется в операционную систему или все открытые буферы удаляются. Операционная система может кэшировать данные перед записью на диск. Функция фиксации на диск гарантирует, что содержимое буфера с очисткой не будет потеряно, если произошел сбой системы.
Существует два способа сохранить зафиксировать содержимое буфера на диске:
- Скомпоновать код с файлом COMMODE.OBJ, чтобы установить глобальный флаг фиксации. По умолчанию этот глобальный флаг имеет значение n , т. е. "не фиксировать".
- Установите флаг режима в c с помощью fopen или _fdopen .
Любой файл, открытый с флагом c или n , ведет себя в соответствии со значением флага, вне зависимости от состояния глобального флага фиксации.
Если программа не закрывает поток явным образом, поток автоматически закрывается при завершении программы. Следует, однако, закрывать поток, когда программа завершает работу с ним, так как количество потоков, которые могут одновременно быть открыты, ограничено. Дополнительные сведения об этом ограничении см _setmaxstdio . в этой статье.
Ввод может следовать сразу за выводом только с промежуточным вызовом fflush или функции позиционирования в файле ( fseek , fsetpos или rewind ). За входными данными можно следовать без промежуточного вызова функции размещения файлов, если входная операция встречает конец файла.
Что такое поток вывода и ввода
Не понимаю, что такое поток вывода и ввода? Поток представляю как отдельный процесс, который работает независимо от других процессов, но как это связано с std::cout и std::cin ? Не могу это никак представить
Отслеживать
задан 18 дек 2022 в 21:26
535 2 2 серебряных знака 7 7 бронзовых знаков
Поток не выполнения, а поток символов/данных. Так проще понять?
18 дек 2022 в 21:28
Если грубо, то поток ввода - это место, откуда вам приходят данные. Часто это терминал. Но также может быть файл или сокет, например
18 дек 2022 в 21:41
К сожалению "переводчики" использую одно и то же слово "поток" и для thread (поток (можно было бы переводить как "нить") выполняемых машинных инструкций) и для stream (поток символов (байт) пересылаемых между программой и устройством ввода-вывода). Оличие же thread от process обычно заключается в том, что у процесса преполагается наличие независимого от других процессов адресного пространства, а у нескольких threads одного и того же процесса адресное пространство общее.
18 дек 2022 в 22:36
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
"stream" т.е. "поток" По сути, ввод/вывод в языке C++ реализован с помощью потоков. Абстрактно, поток — это последовательность символов, к которым можно получить доступ. Со временем поток может производить или потреблять потенциально неограниченные объемы данных. Поток ввода (или «входной поток») используется для хранения данных, полученных от источника данных: клавиатуры, файла, сети и т.д. Например, пользователь может нажать клавишу на клавиатуре в то время, когда программа не ожидает ввода. Вместо игнорирования нажатия клавиши, данные помещаются во входной поток, где затем ожидают ответа от программы. Поток вывода (или «выходной поток») используется для хранения данных, предоставляемых конкретному потребителю данных: монитору, файлу, принтеру и т.д. При записи данных на устройство вывода, это устройство может быть не готовым принять данные немедленно. Например, принтер все еще может прогреваться, когда программа уже записывает данные в выходной поток. Таким образом, данные будут находиться в потоке вывода до тех пор, пока принтер не начнет их использовать. Некоторые устройства, такие как файлы и сети, могут быть источниками как ввода, так и вывода данных. Хорошая новость заключается в том, что программисту не нужно знать детали взаимодействия потоков с разными устройствами и источниками данных, ему нужно только научиться взаимодействовать с этими потоками для чтения и записи данных.
Отслеживать
ответ дан 18 дек 2022 в 22:21
2,075 1 1 золотой знак 3 3 серебряных знака 11 11 бронзовых знаков
Если текст написан не вами, оформите его как цитату и добавьте ссылку на источник. Иначе это считается плагиатом (за который маленьким программистам массируют копчик).