Слово «поток» было выбрано потому, что оно представляет (в реальной жизни) значение, очень похожее на то, что мы хотим передать, когда используем его.
Давайте немного забудем о запасном магазине и начнем думать об аналогии с водным потоком. Вы получаете непрерывный поток данных, точно так же, как вода непрерывно течет в реке. Вы не обязательно знаете, откуда поступают данные, и чаще всего вам это не нужно; будь то файл, сокет или любой другой источник, это не имеет (не должно) никакого значения. Это очень похоже на получение струи воды, при которой вам не нужно знать, откуда она исходит; будь то озеро, фонтан или любой другой источник, это не имеет значения.
Тем не менее, как только вы начинаете думать, что вам нужны только те данные, которые вам нужны, независимо от того, откуда они берутся, абстракции, о которых говорили другие, становятся более ясными. Вы начинаете думать, что можете обернуть потоки, и ваши методы все равно будут работать идеально. Например, вы можете сделать это:
int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); }
// in another method:
Stream fileStream = new FileStream("My Data.dat");
Stream zipStream = new ZipDecompressorStream(fileStream);
Stream decryptedStream = new DecryptionStream(zipStream);
StreamReader reader = new StreamReader(decryptedStream);
int x = ReadInt(reader);
Как видите, становится очень легко изменить источник входного сигнала без изменения логики обработки. Например, чтобы прочитать ваши данные из сетевого сокета вместо файла:
Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);
Так легко, как это может быть. И красота продолжается, так как вы можете использовать любой источник ввода, если вы можете создать для него потоковую «обертку». Вы могли бы даже сделать это:
public class RandomNumbersStreamReader : StreamReader {
private Random random = new Random();
public String ReadLine() { return random.Next().ToString(); }
}
// and to call it:
int x = ReadInt(new RandomNumbersStreamReader());
Видеть? Пока ваш метод не заботится о том, что является источником ввода, вы можете настроить его различными способами. Абстракция позволяет очень элегантно отделить ввод от логики обработки.
Обратите внимание, что созданный нами поток не имеет резервного хранилища, но он по-прежнему отлично подходит для наших целей.
Итак, подведем итог: поток - это просто источник ввода, скрывающий (абстрагирующий) другой источник. Пока вы не нарушите абстракцию, ваш код будет очень гибким.
ReadInt
определен в самом верху используя методint.Parse
, который получает возвращаемую строкуreader.ReadLine()
и анализирует ее. Конечно, вы можете создать аналогичныйReadString
метод. Это достаточно ясно?Stream.Copy
значительно облегчает жизнь во многих приложениях.Дело в том, что вам не нужно знать, что такое резервное хранилище - это абстракция над ним. Действительно, может даже не быть резервного хранилища - вы могли бы читать из сети, и данные никогда вообще не «хранятся».
Если вы можете написать код, который работает независимо от того, говорите ли вы с файловой системой, памятью, сетью или чем-то еще, поддерживающим идею потока, ваш код будет намного более гибким.
Кроме того, потоки часто объединяются в цепочки - у вас может быть поток, который сжимает все, что в него помещено, записывает сжатую форму в другой поток или тот, который шифрует данные и т. Д. На другом конце будет обратное. цепь, расшифровка, распаковка или что-то еще.
источник
StreamReader
- или лучше,TextReader
то ваш код не знает, какой поток лежит в основе потока данных. Или, скорее, он может использоватьBaseStream
свойство для определения типа - но это может быть тип, которого ваш код никогда не видел раньше. Дело в том, что вам все равно. И да, вы можете абсолютно писать код , который будет иногда использоваться для сетевого потока , и иногда можно использовать для файлового потока. Что касается потоков, передающих данные через процесс - ну, это не будет сделано внутри процесса ... это будет поставщик потоков.Суть потока заключается в обеспечении уровня абстракции между вами и резервным хранилищем. Таким образом, для данного блока кода, который использует поток, не нужно заботиться о том, является ли хранилище данных дисковым файлом, памятью и т. Д.
источник
Дело не в ручьях, а в плавании. Если вы можете плыть одним потоком, то вы можете плыть любым потоком, который встречаете.
источник
Чтобы добавить в эхо-камеру, поток - это абстракция, поэтому вам нет дела до основного хранилища. Это имеет смысл, когда вы рассматриваете сценарии с потоками и без них.
Файлы по большей части неинтересны, потому что потоки не делают ничего сверх того, что делали не основанные на потоках методы, с которыми я знаком. Начнем с интернет-файлов.
Если я хочу загрузить файл из Интернета, я должен открыть сокет TCP, установить соединение и получать байты, пока байтов больше нет. Я должен управлять буфером, знать размер ожидаемого файла и писать код, чтобы определить, когда разрывается соединение, и обработать это соответствующим образом.
Допустим, у меня есть какой-то объект TcpDataStream. Я создаю его с соответствующей информацией о соединении, затем читаю байты из потока, пока не будет сказано, что байтов больше нет. Поток обрабатывает управление буфером, условия окончания данных и управление соединением.
Таким образом, потоки облегчают ввод / вывод. Конечно, вы могли бы написать класс TcpFileDownloader, который делает то же, что и поток, но тогда у вас есть класс, специфичный для TCP. Большинство потоковых интерфейсов просто предоставляют методы Read () и Write (), а любые более сложные концепции обрабатываются внутренней реализацией. Из-за этого вы можете использовать один и тот же базовый код для чтения или записи в память, дисковые файлы, сокеты и многие другие хранилища данных.
источник
Визуализация, которую я использую, - это конвейерные ленты, не на реальных фабриках, потому что я ничего об этом не знаю, а на мультипликационных фабриках, где предметы движутся по линиям и получают штампы, коробки, подсчитывают и проверяют с помощью последовательности глупых устройств.
У вас есть простые компоненты, которые делают одно, например, устройство для нанесения вишни на торт. Это устройство имеет входной поток тортов без вишни и выходной поток тортов с вишней. Есть три преимущества, о которых стоит упомянуть, структурируя вашу обработку таким образом.
Во-первых, это упрощает сами компоненты: если вы хотите положить шоколадную глазурь на торт, вам не нужно сложное устройство, которое знает все о пирогах, вы можете создать тупое устройство, которое наклеивает шоколадную глазурь на все, что подается в него (в мультфильмы, это доходит до того, что мы не знаем, что следующий предмет не торт, это Уайл Э. Койот).
Во-вторых, вы можете создавать разные продукты, помещая устройства в разные последовательности: возможно, вы хотите, чтобы ваши пирожные имели глазурь поверх вишни вместо вишни поверх глазури, и вы можете сделать это, просто поменяв устройства на линии. ,
В-третьих, устройствам не нужно управлять инвентарем, упаковкой или распаковкой. Самый эффективный способ агрегирования и упаковки вещей может быть изменен: возможно, сегодня вы складываете свои пирожные в коробки по 48 штук и отправляете их на грузовиках, но завтра вы захотите разослать коробки по шесть в ответ на индивидуальные заказы. Такое изменение может быть осуществлено путем замены или перенастройки машин в начале и в конце производственной линии; Вишневая машина в середине строки не должна изменяться для обработки различного количества элементов за раз, она всегда работает с одним элементом за раз, и ей не нужно знать, каков ее ввод или вывод будучи сгруппированным.
источник
Когда я впервые услышал о потоковой передаче, это было в контексте прямой трансляции с веб-камеры. Итак, один хост транслирует видео контент, а другой хост получает видео контент. Так это потоковое? Ну ... да ... но прямой эфир - это конкретная концепция, и я думаю, что этот вопрос относится к абстрактной концепции потоковой передачи. Смотрите https://en.wikipedia.org/wiki/Live_streaming
Итак, давайте двигаться дальше.
Видео - не единственный ресурс, который можно транслировать. Аудио также может передаваться в потоковом режиме. Итак, мы сейчас говорим о потоковом медиа. Смотрите https://en.wikipedia.org/wiki/Streaming_media . Аудио может быть доставлено от источника к цели множеством способов. Итак, давайте сравним некоторые методы доставки данных друг с другом.
Загрузка классического файла Загрузка классического файла не происходит в режиме реального времени. Прежде чем приступить к использованию файла, вам придется подождать, пока загрузка не будет завершена.
Прогрессивная загрузка Части прогрессивной загрузки загружают данные из потокового медиа-файла во временный буфер. Данные в этом буфере работоспособны: аудио-видео данные в буфере воспроизводимы. Благодаря этому пользователи могут смотреть / слушать потоковый медиафайл во время загрузки. Возможна быстрая перемотка вперед и назад, вне буфера. В любом случае, прогрессивная загрузка - это не прямая трансляция.
Потоковая передача происходит в режиме реального времени и порции данных. Потоковая передача реализована в прямом эфире. Клиенты, слушающие трансляцию, не могут перематывать вперед или назад. В видеопотоках данные отбрасываются после воспроизведения.
Потоковый сервер поддерживает двустороннее соединение со своим клиентом, а веб-сервер закрывает соединение после ответа сервера.
Аудио и видео не единственное, что можно транслировать. Давайте посмотрим на концепцию потоков в руководстве по PHP.
В PHP ресурс - это ссылка на внешний источник, такой как файл, соединение с базой данных. Другими словами, поток - это источник, который можно прочитать или записать. Итак, если вы работали с
fopen()
, то вы уже работали с потоками.Пример текстового файла, который подвергается потоковой передаче:
Zip-файлы также могут быть потоковыми. Кроме того, потоковая передача не ограничивается файлами. HTTP, FTP, SSH соединения и ввод / вывод также могут быть потоковыми.
Что википедия говорит о концепции потоковой передачи?
Смотрите: https://en.wikipedia.org/wiki/Stream_%28computing%29 .
Википедия ссылается на это: https://srfi.schemers.org/srfi-41/srfi-41.html, и авторы могут сказать следующее о потоках:
Таким образом, поток на самом деле является структурой данных.
Мой вывод: поток - это источник, который может содержать данные, которые можно читать или записывать в последовательном порядке. Поток не читает сразу все, что содержит источник, он читает / записывает последовательно.
Полезные ссылки:
источник
Это просто концепция, еще один уровень абстракции, который делает вашу жизнь проще. И все они имеют общий интерфейс, что означает, что вы можете комбинировать их как в трубе. Например, кодировать в base64, затем архивировать, а затем записать это на диск и все в одну строку!
источник
Лучшее объяснение потоков, которые я видел, это глава 3 SICP . (Возможно, вам придется прочитать первые 2 главы, чтобы это имело смысл, но в любом случае вам следует. :-)
Они вообще не используют стерамы для байтов, а целые числа. Большие моменты, которые я получил от этого, были:
источник
Еще один момент (для чтения файла ситуации):
stream
может позволить вам сделать что-то еще, прежде чемfinished reading all content of the file
.источник
Думайте о потоках как об абстрактном источнике данных (байты, символы и т. Д.). Они абстрагируют реальную механику чтения и записи в конкретный источник данных, будь то сетевой сокет, файл на диске или ответ от веб-сервера.
источник
Я думаю, вы должны учитывать, что само хранилище резервных копий часто является просто еще одной абстракцией. Поток памяти довольно легко понять, но файл радикально отличается в зависимости от используемой файловой системы, не говоря уже о том, какой жесткий диск вы используете. На самом деле не все потоки располагаются поверх резервного хранилища: сетевые потоки в основном являются потоками.
Суть потока в том, что мы ограничиваем наше внимание тем, что важно. Имея стандартную абстракцию, мы можем выполнять обычные операции. Даже если вы не хотите, например, искать файл или ответ HTTP для URL сегодня, это не значит, что вы не захотите завтра.
Потоки изначально задумывались, когда память была крошечной по сравнению с памятью. Просто чтение файла C может быть значительной нагрузкой. Минимизация объема памяти была чрезвычайно важна. Следовательно, абстракция, в которой очень мало нужно было загружать, была очень полезна. Сегодня он одинаково полезен при выполнении сетевых коммуникаций и, как оказывается, редко бывает настолько ограничительным, когда мы имеем дело с файлами. Возможность прозрачного добавления таких вещей, как буферизация, делает это еще более полезным.
источник
Поток - это абстракция последовательности байтов. Идея состоит в том, что вам не нужно знать, откуда поступают байты, просто вы можете читать их стандартным образом.
Например, если вы обрабатываете данные через поток, то для вашего кода не имеет значения, поступают ли данные из файла, сетевого подключения, строки, большого двоичного объекта в базе данных и т. Д. И т. Д. И т. Д.
Нет ничего плохого в том, чтобы взаимодействовать с самим резервным хранилищем, за исключением того факта, что это связывает вас с реализацией резервного хранилища.
источник
Поток - это абстракция, которая предоставляет стандартный набор методов и свойств для взаимодействия с данными. Абстрагируясь от фактического носителя, ваш код может быть написан без полной зависимости от того, что это за носитель или даже от реализации этого носителя.
Хорошей аналогией может быть рассмотрение сумки. Вас не волнует, из чего сделана сумка или что она делает, когда вы кладете в нее свои вещи, если сумка выполняет роль сумки, и вы можете вернуть свои вещи обратно. Поток определяет для носителей, что определяет концепция сумки для разных экземпляров сумки (например, сумка для мусора, сумка, рюкзак и т. Д.) - правила взаимодействия.
источник
Я буду кратким, я просто пропустил слово здесь:
Потоки - это очереди обычно хранятся в буфере, содержащем данные любого типа.
(Теперь, поскольку мы все знаем, что такое очереди, нет необходимости объяснять это дальше.)
источник