Что такое поток?


Ответы:


161

Поток представляет собой последовательность объектов (обычно байтов, но не обязательно), к которым можно получить доступ в последовательном порядке. Типичные операции над потоком:

  • прочитать один байт. В следующий раз, когда вы прочтете, вы получите следующий байт и так далее.
  • прочитать несколько байтов из потока в массив
  • seek (переместите вашу текущую позицию в потоке, чтобы при следующем чтении вы получали байты из новой позиции)
  • написать один байт
  • записать несколько байтов из массива в поток
  • пропускать байты из потока (это похоже на чтение, но вы игнорируете данные. Или, если вы предпочитаете, это похоже на поиск, но может идти только вперед).
  • вернуть байты во входной поток (это похоже на «отменить» для чтения - вы вставляете несколько байтов обратно в поток, так что в следующий раз, когда вы читаете то, что вы увидите. Иногда это полезно для парсеров, например:
  • peek (смотрите байты, не читая их, чтобы они все еще были в потоке для последующего чтения)

Конкретный поток может поддерживать чтение (в этом случае это «входной поток»), запись («выходной поток») или и то, и другое. Не все потоки доступны для поиска.

Возврат осуществляется довольно редко, но вы всегда можете добавить его в поток, заключив реальный входной поток в другой входной поток, содержащий внутренний буфер. Чтения происходят из буфера, и если вы вернетесь, данные будут помещены в буфер. Если в буфере ничего нет, то поток обратной передачи считывает реальный поток. Это простой пример «адаптера потока»: он находится на «конце» входного потока, он сам является входным потоком и делает что-то дополнительное, чего не делал исходный поток.

Поток - это полезная абстракция, потому что он может описывать файлы (которые на самом деле являются массивами, следовательно, поиск прост), а также ввод / вывод терминала (который недоступен для поиска, если не буферизован), сокеты, последовательные порты и т. Д. Таким образом, вы можете написать код, который говорит либо «Мне нужны какие-то данные, и меня не волнует, откуда они и как они попали сюда», либо «Я создам некоторые данные, и все зависит от вызывающего абонента, что с ними произойдет». Первый принимает параметр входного потока, второй - параметр выходного потока.

Лучшая аналогия, которую я могу придумать, - это то, что поток - это конвейерная лента, идущая к вам или уводящая от вас (а иногда и то и другое). Вы берете материал из входного потока, вы помещаете материал в выходной поток. Некоторые конвейеры, которые можно представить себе как выходящие из дыры в стене, недоступны для поиска, чтение или письмо - это одноразовая сделка. Некоторые конвейеры проложены перед вами, и вы можете двигаться вперед, выбирая место в потоке, которое вы хотите читать / писать - это и есть поиск.

Однако, как говорит IRBMe, лучше рассматривать поток с точки зрения предлагаемых им операций (которые различаются от реализации к реализации, но имеют много общего), а не по физической аналогии. Потоки - это «вещи, которые вы можете читать или писать». Когда вы начинаете подключать адаптеры восходящего потока, вы можете думать о них как о блоке с конвейером на входе и конвейером на выходе, который вы подключаете к другим потокам, а затем ящик выполняет некоторые преобразования данных (их архивирование или изменение строк в UNIX. в DOS или что-то еще). Каналы - еще одна тщательная проверка метафоры: здесь вы создаете пару потоков, так что все, что вы пишете в один, можно прочитать из другого. Подумайте о червоточинах :-)


3
Безусловно, лучшее объяснение, которое я читал. В сочетании с тем, что говорится в SICP («Потоковая обработка позволяет нам моделировать системы, у которых есть состояние, без использования присваивания или изменяемых данных»), думаю, я наконец понял это. Спасибо!
Кайл Чада

86

Поток - это уже метафора, аналогия, поэтому нет необходимости приводить еще один. Вы можете думать об этом в основном как о трубе с потоком воды в ней, где вода на самом деле является данными, а труба - потоком. Я полагаю, это своего рода двухсторонняя труба, если поток двунаправленный. По сути, это обычная абстракция, которая применяется к вещам, где есть поток или последовательность данных в одном или обоих направлениях.

В таких языках, как C #, VB.Net, C ++, Java и т. Д., Метафора потока используется для многих вещей. Существуют файловые потоки, в которых вы открываете файл и можете постоянно читать из потока или записывать в него; Существуют сетевые потоки, в которых чтение и запись в поток считываются и записываются в базовое установленное сетевое соединение. Потоки только для записи обычно называются выходными потоками, как в этом примере, и аналогично потоки, предназначенные только для чтения, называются входными потоками, как в этом примере.

Поток может выполнять преобразование или кодирование данных ( например, SslStream в .Net съест данные согласования SSL и скроет их от вас; TelnetStream может скрыть от вас переговоры Telnet, но предоставить доступ к данным; A ZipOutputStream в Java позволяет вам записывать файлы в zip-архиве, не беспокоясь о внутреннем устройстве формата zip-файла.

Еще одна распространенная вещь, которую вы можете найти, - это текстовые потоки, которые позволяют вам писать строки вместо байтов, или некоторые языки предоставляют двоичные потоки, которые позволяют вам писать примитивные типы. Обычная вещь, которую вы найдете в текстовых потоках, - это кодировка символов, о которой вам следует знать.

Некоторые потоки также поддерживают произвольный доступ, как в этом примере. С другой стороны, сетевой поток по понятным причинам не будет.

  • MSDN дает хороший обзор потоков в .Net.
  • У Sun также есть обзор их общего класса OutputStream и класса InputStream .
  • В C ++ представлена ​​документация по istream (входной поток), ostream (выходной поток) и iostream (двунаправленный поток).

UNIX-подобные операционные системы также поддерживают потоковую модель с программным вводом и выводом, как описано здесь .


13

Пока что даны отличные ответы. Я лишь предлагаю другой, чтобы подчеркнуть, что поток не является последовательностью байтов или специфичен для языка программирования, поскольку концепция универсальна (хотя ее реализация может быть уникальной). Я часто вижу в Интернете множество объяснений в терминах SQL, C или Java, которые имеют смысл, поскольку файловый поток имеет дело с ячейками памяти и низкоуровневыми операциями. Но они часто обращаются к тому, как создать файловый поток и работать с потенциальным файлом на своем заданном языке, а не обсуждают концепцию потока.

Метафора

Как уже упоминалось, a stream- это метафора, абстракция чего-то более сложного. Чтобы ваше воображение заработало, предлагаю еще несколько метафор:

  1. вы хотите наполнить пустой бассейн водой. один из способов добиться этого - прикрепить шланг к патрубку, поместить конец шланга в бассейн и включить воду.

шланг это ручей

  1. аналогично, если вы хотите заправить свою машину бензином, вы должны подойти к бензоколонке, вставить форсунку в свой бензобак и открыть клапан, нажав на фиксирующий рычаг.

шланг, сопло и связанные механизмы, позволяющие газу течь в ваш резервуар, - это поток

  1. если вам нужно добраться до работы, вы начнете ехать из дома в офис по автостраде.

автострада это ручей

  1. если вы хотите поговорить с кем-то, вы должны использовать уши, чтобы слышать, и рот, чтобы говорить.

твои уши и глаза ручьи

Надеюсь, вы заметили в этих примерах, что метафоры потока существуют только для того, чтобы позволить чему-то перемещаться по нему (или по нему в случае автострады), и сами не всегда представляют собой то, что они передают. Важное различие. Мы не относимся к нашим ушам как к последовательности слов. Шланг по-прежнему остается шлангом, если по нему не течет вода, но мы должны подсоединить его к патрубку, чтобы он правильно выполнял свою работу. Автомобиль - не единственный вид транспорта, который может пересекать автостраду.

Таким образом, может существовать поток, по которому не проходят данные, пока он подключен к файлу .

Удаление абстракции

Далее нам нужно ответить на несколько вопросов. Я собираюсь использовать файлы для описания потоков, поэтому ... Что такое файл? А как мы читаем файл? Я попытаюсь ответить на этот вопрос, сохраняя определенный уровень абстракции, чтобы избежать ненужной сложности, и буду использовать концепцию файла относительно операционной системы Linux из-за ее простоты и доступности.

Что такое файл?

Файл - это абстракция :)

Или, как я могу объяснить, файл - это структура данных одной части, описывающая файл, и данные одной части, которые являются фактическим содержимым.

Часть структуры данных (называемая индексным дескриптором в системах UNIX / Linux) идентифицирует важную информацию о содержимом, но не включает в себя сам контент (или имя файла, если на то пошло). Одна из частей информации, которую он хранит, - это адрес памяти, с которого начинается контент. Таким образом, с именем файла (или жесткой ссылкой в ​​Linux), дескриптором файла (числовым именем файла, о котором заботится операционная система) и начальным местоположением в памяти у нас есть то, что мы можем назвать файлом.

(ключевой вывод - это «файл», который определяется операционной системой, поскольку именно ОС, в конечном счете, должна иметь дело с ним. И да, файлы намного сложнее).

Все идет нормально. Но как нам получить содержимое файла, например, любовное письмо своему парню, чтобы мы могли его распечатать?

Чтение файла

Если мы начнем с результата и движемся назад, когда мы открываем файл на нашем компьютере, все его содержимое отображается на экране, чтобы мы могли его прочитать. Но как? Очень методичный ответ. Само содержимое файла представляет собой другую структуру данных. Предположим, массив символов. Мы также можем думать об этом как о строке.

Так как же нам «прочитать» эту строку? Находя его местоположение в памяти и просматривая наш массив символов, по одному символу за раз, пока не будет достигнут символ конца файла. Другими словами программа.

Поток «создается», когда вызывается его программа, и у него есть место в памяти для подключения или подключения . Как и в нашем примере с водяным шлангом, шланг неэффективен, если он не подключен к патрубку. В случае потока он должен быть подключен к файлу, чтобы он существовал.

Потоки могут быть дополнительно уточнены, например, поток для приема ввода или поток для отправки содержимого файлов на стандартный вывод. UNIX / linux сразу же подключает и сохраняет для нас открытыми 3 файловых потока: stdin (стандартный ввод), stdout (стандартный вывод) и stderr (стандартная ошибка). Потоки могут быть построены как сами структуры данных или как объекты, что позволяет нам выполнять более сложные операции потоковой передачи данных через них, такие как открытие потока, закрытие потока или проверка ошибок файла, к которому подключен поток. C ++ cin- это пример объекта потока.

Конечно, если вы захотите, вы можете написать свой собственный поток.

Определение

Поток - это многократно используемый фрагмент кода, который абстрагирует сложность работы с данными, обеспечивая при этом полезные операции для выполнения с данными.


Таким образом, поток - это среда, через которую проходят данные. Он должен быть подключен к источнику данных, и он может выполнять операции над собой и данными, проходящими через него.
KingBryan

да. Моя единственная причина написать дополнительный ответ - это пояснить, что поток может существовать, даже если данные не проходят через него. тогда как поток IRL (с водой и т.п.) перестает быть потоком, когда вода перестает течь, и может вызвать путаницу при размышлении об аналогии.
rekurzion

1
В настоящее время я изучаю Java, и ваш ответ помог мне понять это.
KingBryan

6

В дополнение к вещам, упомянутым выше, существует другой вид потоков - как определено в языках функционального программирования, таких как Scheme или Haskell - возможно, бесконечная структура данных, которая генерируется некоторой функцией по запросу.


6

Еще одна аналогия: нельзя плыть против потока, поэтому можно просто взять из потока следующий бит, байт, строку или объект, при этом уже прочитанные данные удаляются. Билет в один конец ... или просто очередь без сохранения.

Так нам нужны очереди? Вам решать.


это означает, что в потоке вы должны идти вперед и не можете двигаться назад. Кроме того, предыдущие данные удаляются по мере продвижения вперед, что сохраняет память? Верно
Мухаммад Файзан Хан

5

Слово «поток» было выбрано потому, что оно представляет (в реальной жизни) значение, очень похожее на то, что мы хотим передать, когда его используем.

Придумайте аналогию с водным потоком. Вы получаете непрерывный поток данных, как вода в реке. Вы не обязательно знаете, откуда берутся данные, и чаще всего вам это не нужно; будь то из файла, сокета или любого другого источника, это не имеет (не должно) особого значения. Это очень похоже на получение потока воды, при котором вам не нужно знать, откуда она идет; будь то из озера, фонтана или любого другого источника, это не имеет (не должно) особого значения. источник

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.