Ответы:
Поток представляет собой последовательность объектов (обычно байтов, но не обязательно), к которым можно получить доступ в последовательном порядке. Типичные операции над потоком:
Конкретный поток может поддерживать чтение (в этом случае это «входной поток»), запись («выходной поток») или и то, и другое. Не все потоки доступны для поиска.
Возврат осуществляется довольно редко, но вы всегда можете добавить его в поток, заключив реальный входной поток в другой входной поток, содержащий внутренний буфер. Чтения происходят из буфера, и если вы вернетесь, данные будут помещены в буфер. Если в буфере ничего нет, то поток обратной передачи считывает реальный поток. Это простой пример «адаптера потока»: он находится на «конце» входного потока, он сам является входным потоком и делает что-то дополнительное, чего не делал исходный поток.
Поток - это полезная абстракция, потому что он может описывать файлы (которые на самом деле являются массивами, следовательно, поиск прост), а также ввод / вывод терминала (который недоступен для поиска, если не буферизован), сокеты, последовательные порты и т. Д. Таким образом, вы можете написать код, который говорит либо «Мне нужны какие-то данные, и меня не волнует, откуда они и как они попали сюда», либо «Я создам некоторые данные, и все зависит от вызывающего абонента, что с ними произойдет». Первый принимает параметр входного потока, второй - параметр выходного потока.
Лучшая аналогия, которую я могу придумать, - это то, что поток - это конвейерная лента, идущая к вам или уводящая от вас (а иногда и то и другое). Вы берете материал из входного потока, вы помещаете материал в выходной поток. Некоторые конвейеры, которые можно представить себе как выходящие из дыры в стене, недоступны для поиска, чтение или письмо - это одноразовая сделка. Некоторые конвейеры проложены перед вами, и вы можете двигаться вперед, выбирая место в потоке, которое вы хотите читать / писать - это и есть поиск.
Однако, как говорит IRBMe, лучше рассматривать поток с точки зрения предлагаемых им операций (которые различаются от реализации к реализации, но имеют много общего), а не по физической аналогии. Потоки - это «вещи, которые вы можете читать или писать». Когда вы начинаете подключать адаптеры восходящего потока, вы можете думать о них как о блоке с конвейером на входе и конвейером на выходе, который вы подключаете к другим потокам, а затем ящик выполняет некоторые преобразования данных (их архивирование или изменение строк в UNIX. в DOS или что-то еще). Каналы - еще одна тщательная проверка метафоры: здесь вы создаете пару потоков, так что все, что вы пишете в один, можно прочитать из другого. Подумайте о червоточинах :-)
Поток - это уже метафора, аналогия, поэтому нет необходимости приводить еще один. Вы можете думать об этом в основном как о трубе с потоком воды в ней, где вода на самом деле является данными, а труба - потоком. Я полагаю, это своего рода двухсторонняя труба, если поток двунаправленный. По сути, это обычная абстракция, которая применяется к вещам, где есть поток или последовательность данных в одном или обоих направлениях.
В таких языках, как C #, VB.Net, C ++, Java и т. Д., Метафора потока используется для многих вещей. Существуют файловые потоки, в которых вы открываете файл и можете постоянно читать из потока или записывать в него; Существуют сетевые потоки, в которых чтение и запись в поток считываются и записываются в базовое установленное сетевое соединение. Потоки только для записи обычно называются выходными потоками, как в этом примере, и аналогично потоки, предназначенные только для чтения, называются входными потоками, как в этом примере.
Поток может выполнять преобразование или кодирование данных ( например, SslStream в .Net съест данные согласования SSL и скроет их от вас; TelnetStream может скрыть от вас переговоры Telnet, но предоставить доступ к данным; A ZipOutputStream в Java позволяет вам записывать файлы в zip-архиве, не беспокоясь о внутреннем устройстве формата zip-файла.
Еще одна распространенная вещь, которую вы можете найти, - это текстовые потоки, которые позволяют вам писать строки вместо байтов, или некоторые языки предоставляют двоичные потоки, которые позволяют вам писать примитивные типы. Обычная вещь, которую вы найдете в текстовых потоках, - это кодировка символов, о которой вам следует знать.
Некоторые потоки также поддерживают произвольный доступ, как в этом примере. С другой стороны, сетевой поток по понятным причинам не будет.
UNIX-подобные операционные системы также поддерживают потоковую модель с программным вводом и выводом, как описано здесь .
Пока что даны отличные ответы. Я лишь предлагаю другой, чтобы подчеркнуть, что поток не является последовательностью байтов или специфичен для языка программирования, поскольку концепция универсальна (хотя ее реализация может быть уникальной). Я часто вижу в Интернете множество объяснений в терминах SQL, C или Java, которые имеют смысл, поскольку файловый поток имеет дело с ячейками памяти и низкоуровневыми операциями. Но они часто обращаются к тому, как создать файловый поток и работать с потенциальным файлом на своем заданном языке, а не обсуждают концепцию потока.
Как уже упоминалось, a stream
- это метафора, абстракция чего-то более сложного. Чтобы ваше воображение заработало, предлагаю еще несколько метафор:
шланг это ручей
шланг, сопло и связанные механизмы, позволяющие газу течь в ваш резервуар, - это поток
автострада это ручей
твои уши и глаза ручьи
Надеюсь, вы заметили в этих примерах, что метафоры потока существуют только для того, чтобы позволить чему-то перемещаться по нему (или по нему в случае автострады), и сами не всегда представляют собой то, что они передают. Важное различие. Мы не относимся к нашим ушам как к последовательности слов. Шланг по-прежнему остается шлангом, если по нему не течет вода, но мы должны подсоединить его к патрубку, чтобы он правильно выполнял свою работу. Автомобиль - не единственный вид транспорта, который может пересекать автостраду.
Таким образом, может существовать поток, по которому не проходят данные, пока он подключен к файлу .
Далее нам нужно ответить на несколько вопросов. Я собираюсь использовать файлы для описания потоков, поэтому ... Что такое файл? А как мы читаем файл? Я попытаюсь ответить на этот вопрос, сохраняя определенный уровень абстракции, чтобы избежать ненужной сложности, и буду использовать концепцию файла относительно операционной системы Linux из-за ее простоты и доступности.
Файл - это абстракция :)
Или, как я могу объяснить, файл - это структура данных одной части, описывающая файл, и данные одной части, которые являются фактическим содержимым.
Часть структуры данных (называемая индексным дескриптором в системах UNIX / Linux) идентифицирует важную информацию о содержимом, но не включает в себя сам контент (или имя файла, если на то пошло). Одна из частей информации, которую он хранит, - это адрес памяти, с которого начинается контент. Таким образом, с именем файла (или жесткой ссылкой в Linux), дескриптором файла (числовым именем файла, о котором заботится операционная система) и начальным местоположением в памяти у нас есть то, что мы можем назвать файлом.
(ключевой вывод - это «файл», который определяется операционной системой, поскольку именно ОС, в конечном счете, должна иметь дело с ним. И да, файлы намного сложнее).
Все идет нормально. Но как нам получить содержимое файла, например, любовное письмо своему парню, чтобы мы могли его распечатать?
Если мы начнем с результата и движемся назад, когда мы открываем файл на нашем компьютере, все его содержимое отображается на экране, чтобы мы могли его прочитать. Но как? Очень методичный ответ. Само содержимое файла представляет собой другую структуру данных. Предположим, массив символов. Мы также можем думать об этом как о строке.
Так как же нам «прочитать» эту строку? Находя его местоположение в памяти и просматривая наш массив символов, по одному символу за раз, пока не будет достигнут символ конца файла. Другими словами программа.
Поток «создается», когда вызывается его программа, и у него есть место в памяти для подключения или подключения . Как и в нашем примере с водяным шлангом, шланг неэффективен, если он не подключен к патрубку. В случае потока он должен быть подключен к файлу, чтобы он существовал.
Потоки могут быть дополнительно уточнены, например, поток для приема ввода или поток для отправки содержимого файлов на стандартный вывод. UNIX / linux сразу же подключает и сохраняет для нас открытыми 3 файловых потока: stdin (стандартный ввод), stdout (стандартный вывод) и stderr (стандартная ошибка). Потоки могут быть построены как сами структуры данных или как объекты, что позволяет нам выполнять более сложные операции потоковой передачи данных через них, такие как открытие потока, закрытие потока или проверка ошибок файла, к которому подключен поток. C ++ cin
- это пример объекта потока.
Конечно, если вы захотите, вы можете написать свой собственный поток.
Поток - это многократно используемый фрагмент кода, который абстрагирует сложность работы с данными, обеспечивая при этом полезные операции для выполнения с данными.
Еще одна аналогия: нельзя плыть против потока, поэтому можно просто взять из потока следующий бит, байт, строку или объект, при этом уже прочитанные данные удаляются. Билет в один конец ... или просто очередь без сохранения.
Так нам нужны очереди? Вам решать.
Слово «поток» было выбрано потому, что оно представляет (в реальной жизни) значение, очень похожее на то, что мы хотим передать, когда его используем.
Придумайте аналогию с водным потоком. Вы получаете непрерывный поток данных, как вода в реке. Вы не обязательно знаете, откуда берутся данные, и чаще всего вам это не нужно; будь то из файла, сокета или любого другого источника, это не имеет (не должно) особого значения. Это очень похоже на получение потока воды, при котором вам не нужно знать, откуда она идет; будь то из озера, фонтана или любого другого источника, это не имеет (не должно) особого значения. источник