你能解释stream的概念吗?

我知道一个stream是一个字节序列的表示。 每个stream提供了读写字节到其给定的后备存储的手段。 但是stream的重点是什么? 为什么后台不存储我们与之交互的内容?

无论出于何种原因,这个概念只是不点击我。 我读了一大堆文章,但我想我需要一个类比或什么东西。

“stream”这个词已经被选中,因为它代表了(在现实生活中)与我们在使用它时要expression的意思非常相似的意思。

让我们忘记一点支持商店,并开始考虑类似于水stream。 你会收到一个连续的数据stream,就像水在河中不断stream动一样。 你不一定知道数据来自哪里,大多数情况下你不需要; 无论是从文件,套接字或其他来源,它不(不应该)真正重要。 这与接收水stream非常相似,因此您不需要知道它来自哪里。 无论是湖泊,喷泉还是其他来源,它都不是(不应该)真的很重要。

也就是说,一旦你开始思考,你只关心获取你需要的数据,不pipe从哪里来,其他人谈论的抽象就会变得更清晰。 你开始认为你可以打包stream,你的方法仍然可以完美的工作。 例如,你可以这样做:

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); 

如您所见,在不改变处理逻辑的情况下更改input源将变得非常容易。 例如,要从networking套接字而不是文件中读取数据:

 Stream stream = new NetworkStream(mySocket); StreamReader reader = new StreamReader(stream); int x = ReadInt(reader); 

尽可能简单。 而且这个美丽继续下去,因为你可以使用任何types的input源,只要你可以为它创build一个stream“包装器”。 你甚至可以这样做:

 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()); 

看到? 只要你的方法不关心input源是什么,你可以以各种方式定制你的源代码。 抽象允许您以非常优雅的方式将input从处理逻辑中分离出来。

请注意,我们自己创build的stream没有后备存储,但它仍然完美地服务于我们的目的。

所以,总而言之,一个stream只是一个input源,隐藏(抽象)另一个源。 只要你不打破抽象,你的代码将非常灵活。

关键是你不应该知道后台存储是什么 – 这是一个抽象的。 事实上,甚至可能还没有一个支持商店 – 你可能正在从networking上读取数据,而且数据永远不会被“存储”。

如果你可以编写代码,无论你是在与文件系统,内存,networking还是其他任何支持stream想法的对话,你的代码都更加灵活。

另外,数据stream通常是链接在一起的 – 你可以拥有一个压缩任何内容的stream,将压缩的表单写入另一个stream,或者encryption数据等等。在另一端,会有相反的链,解密,解压缩或其他。

stream的要点是在你和后台存储之间提供一个抽象层。 因此,使用stream的给定代码块不需要关心后备存储是否是磁盘文件,内存等等。

这不是关于溪stream – 而是关于游泳。 如果你可以游泳一条溪stream,那么你可以游泳遇到的任何溪stream。

要添加到回声室,stream是一个抽象,所以你不关心底层商店。 当你考虑有和没有stream的场景时,它是最有意义的。

大部分文件并不感兴趣,因为数据stream并没有超出我所熟悉的非基于数据stream的方法。 让我们从互联网文件开始。

如果我想从互联网下载文件,我必须打开一个TCP套接字,build立连接,并接收字节,直到没有更多的字节。 我必须pipe理一个缓冲区,知道预期文件的大小,并编写代码来检测连接何时被丢弃,并正确处理。

假设我有某种TcpDataStream对象。 我用适当的连接信息创build它,然后从stream中读取字节,直到它说没有更多的字节。 该stream处理缓冲区pipe理,数据结束条件和连接pipe理。

这样,stream使I / O更容易。 你当然可以写一个TcpFileDownloader类来完成stream的function,但是你有一个特定于TCP的类。 大多数stream接口只提供一个Read()和Write()方法,任何更复杂的概念都由内部实现来处理。 因此,您可以使用相同的基本代码来读取或写入内存,磁盘文件,套接字和许多其他数据存储。

这只是一个概念,另一个抽象层次让你的生活更轻松。 他们都有共同的界面,这意味着你可以像pipe道一样把它们组合起来。 例如,编码到base64,然后压缩,然后写入磁盘,并在一行!

我使用的可视化是传送带,而不是在真正的工厂,因为我不知道什么,但是在卡通工厂里,物品沿着线条移动,并被一系列的哑装置打上盖子,装箱,计数和检查。

你有简单的组件来做一件事,例如一个把樱桃放在蛋糕上的设备。 这个设备有一个无樱桃蛋糕的inputstream,和樱桃蛋糕的输出stream。 有三个优点值得一提,就是以这种方式来构build你的处理。

首先,它简化了组件本身:如果你想把巧克力糖衣放在蛋糕上,你不需要一个复杂的设备,知道蛋糕的一切,你可以创build一个愚蠢的设备,坚持巧克力糖衣,漫画,这只是不知道下一个项目不是蛋糕,它是Wile E. Coyote)。

其次,您可以通过将设备设置成不同的顺序来创build不同的产品:也许您希望您的蛋糕在结冰之上有樱桃而不是樱桃,而且您可以简单地通过交换设备周围的设备。

第三,设备不需要pipe理库存,装箱或拆箱。 聚合和包装物品的最有效的方式是多变的:也许今天你将蛋糕装入48箱,然后由卡车发送出去,但是明天你想发送6箱来回应定制订单。 这种改变可以通过在生产线的开始和结束时更换或重新configuration机器来解决。 中间的樱花机不必改变,一次处理不同数量的物品,它一次只能处理一个物品,不需要知道其input或输出是怎样的被分组。

我见过的溪stream的最佳解释是SICP的第3章 。 (您可能需要阅读前两章才能理解,但无论如何你都应该这样做。:-)

他们根本不用字节,而是整数。 我从中得到的重点是:

  • stream是延迟列表
  • 在某些情况下,急于计算所有内容的计算开销太大了
  • 我们可以使用stream来表示无限长的序列

在计算机科学中,一个stream是一个连续的信息stream。

当我想到stream媒体时,我想到了一个video数据传输服务 。 尽pipestream式传输不限于video。 文本,audio,zip文件也可以stream式传输。 最重要的是,stream媒体不仅限于文件。 HTTP,FTP,SSH连接和input/输出也可以stream式传输。

要理解stream式传输的概念,您可以比较其他数据分布概念。

传统的文件下载不会实时发生。 在使用文件之前,您必须等到下载完成。

渐进式下载允许video文件在下载时观看。 快进和倒带是可能的。 要做到这一点,它使用一个缓冲区,将数据临时存储在接收video文件的计算机的内存中。 即使数据被分块,也不是真正的stream媒体。

stream式传输实时发生,并将数据块化。 stream式传输是在直播中实现的。 收听广播的客户不能快进或倒带。 在videostream中,播放后丢弃数据。

Streaming Server与客户端保持双向连接,而Web Server在服务器响应后closures连接。

有用链接:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011提供了非常清晰的演示文稿;
  2. https://www.sk89q.com/2010/04/introduction-to-php-streams/
  3. http://www.netlingo.com/word/stream-or-streaming.php
  4. http://www.brainbell.com/tutorials/php/Using_PHP_Streams.htm
  5. http://www.sitepoint.com/php-streaming-output-buffering-explained/
  6. http://php.net/manual/en/wrappers.php
  7. http://www.digidata-lb.com/streaming/Streaming_Proposal.pdf
  8. http://www.webopedia.com/TERM/S/streaming.html
  9. http://php.net/manual/en/intro.stream.php
  10. https://en.wikipedia.org/wiki/Stream_%28computing%29

另一点(阅读文件情况):

  1. finished reading all content of the file之前, stream可以允许您执行其他finished reading all content of the file
  2. 您可以节省内存,因为不需要一次加载所有文件内容。

将stream视为数据的抽象来源(字节,字符等)。 他们从具体的数据源中抽象出实际的读写机制,无论是networking套接字,磁盘上的文件还是来自Web服务器的响应。

我认为你需要考虑到支持商店本身往往只是另一个抽象。 一个内存stream很容易理解,但是一个文件根据你使用的是哪一个文件系统是完全不同的,不用介意你使用的是什么硬盘。 事实上,并非所有的数据stream都位于备份存储之上:networking数据stream几乎就是数据stream。

stream的一点是我们把注意力限制在重要的事情上。 通过标准的抽象,我们可以执行常见的操作。 即使你不想今天search一个文件或HTTP响应的URL,并不意味着你不会希望明天。

当存储相比存储很小时,stream最初被设想出来。 只是读一个C文件可能是一个重要的负载。 最大限度地减less内存占用非常重要。 因此,很less需要加载的抽象非常有用。 今天,在进行networking通信时,它也同样有用,事实certificate,当我们处理文件时,这种限制很less。 以通用的方式透明地添加缓冲等function使其更加有用。

stream是一个字节序列的抽象。 这个想法是,你不需要知道字节从哪里来,只要你可以以标准化的方式阅读它们。

例如,如果您通过stream处理数据,那么如果数据来自文件,networking连接,string,数据库中的blob等,则与代码无关。

与后台存储本身进行交互除了将其与后台存储实现联系起来之外没有任何问题。

stream是一个抽象,提供了与数据交互的一组标准方法和属性。 通过从实际存储介质中抽象出来,您的代码可以不依赖于介质,甚至是介质的实现。

一个很好的比喻可能是考虑一个包。 只要袋子做袋子的工作,你可以把你的东西拿回来,你不会在意袋子是由什么材料制成的,或者是什么东西。 stream为存储介质定义了包的概念对于包的不同实例(例如垃圾包,手提包,帆布背包等)所定义的交互规则。

我会保持简短,我只是想念这个词:

stream是通常存储在包含任何types数据的缓冲区中的队列

(现在,因为我们都知道队列是什么,所以没有必要进一步解释。)