2009-08-01 60 views
70

编程世界中的流是什么?我们为什么需要它?什么是流?

如果可能,请在类比的帮助下进行解释。

+8

这是http://stackoverflow.com/questions/507747/can-you-explain-the-concept-of-streams的副本。 – 2009-08-01 11:47:51

回答

101

流表示一系列对象(通常是字节,但不一定是这样),它们可以按顺序访问。流上的典型操作:

  • 读取一个字节。下次你阅读,你会得到下一个字节,等等。
  • 从流读取几个字节到一个数组
  • 求(移动你的当前位置的数据流中,以便下次你读你得到新的位置字节时间)
  • 写一个字节
  • 写几篇字节从一个数组流入流
  • 从流中跳过字节(这类似于读取,但您忽略数据,或者如果您更喜欢它就像查找,但只能向前)
  • 将字节推回到输入流(这就像读取“撤消”一样 - 你将几个字节推回到流中,以便下次读取t时帽子就是你会看到的。它是解析器有时候是有用的,因为是:
  • PEEK(看个字节不读它们,让它们还在那里流中稍后阅读)

特定流可能支持读取(在哪种情况下它是“输入流”),写入(“输出流”)或两者。并非所有的流都是可搜索的。

推回相当少见,但您可以通过将实际输入流包装到另一个包含内部缓冲区的输入流中,将其添加到流中。读取来自缓冲区,如果你推回来,那么数据被放入缓冲区。如果缓冲区中没有任何内容,则推回流将从实际流中读取。这是一个“流适配器”的简单示例:它位于输入流的“结尾”,它是一个输入流本身,它做了额外的事情,原始流没有。流是一个有用的抽象,因为它可以描述文件(这是真正的数组,因此寻求是直接的),但也终端输入/输出(这是不可搜索,除非缓冲),套接字,串行端口等。所以你可以编写代码说:“我想要一些数据,我不在乎它来自哪里或它是如何到达这里的”,或者“我将生成一些数据,完全取决于我的调用者它发生了什么”。前者接受输入流参数,后者接受输出流参数。

我能想到的最好的比喻是流是一条传送带向你走来或从你(或有时两者)带走。你从输入流中取出东西,把东西放在输出流上。一些传送带可以被认为是从墙上钻出来的 - 它们不是可追求的,阅读或写作是一次性交易。有些传送带摆放在你的面前,你可以随意选择你想要读/写的小溪中的下落位置 - 这正在寻找。

正如IRBMe所说,尽管最好从流程的角度来考虑它所提供的操作(从实现到实现有所不同,但有很多共同点),而不是物理比喻。流是“你可以读或写的东西”。当你开始连接流适配器时,你可以把它们想象成一个盒子,里面有一个传送带,一个传送带,连接到其他流,然后盒子对数据进行一些转换(压缩或更改UNIX换行符到DOS的,或其他)。管道是隐喻的另一个彻底测试:那就是你创建一对流的地方,这样你写入其中的任何东西都可以被读出。认为虫洞:-)

+1

迄今为止我读过的最好的解释。再加上它在SICP中所说的话(“流处理可以让我们对没有使用任务或可变数据的状态进行建模的系统进行建模。”),我想我终于明白了。谢谢! – 2016-10-08 17:04:50

24

流已经是一个比喻,是一个比喻,所以真的没有必要去提供另一个。你可以把它想象成一个管道,里面有水流,水是实际的数据,管道是水流。如果流是双向的,我想这是一种双向管道。它基本上是一种常见的抽象,它被放置在一个或两个方向上有数据流或数据序列的地方。

在诸如C#,VB.Net,C++,Java等语言中,流隐喻用于很多事情。有文件流,您可以在其中打开文件并可以从流中读取或写入;有一些网络流可以读取和写入流,读取和写入基础的已建立网络连接。仅用于写入的流典型地称为输出流,如在this示例中那样,并且类似地,仅用于读取的流被称为输入流,如在this示例中那样。

流可以执行数据的转换或编码(例如,在.Net中使用SslStream,例如,会吞掉SSL协商数据并将其隐藏起来; TelnetStream可能会隐藏Telnet协商,但可以访问数据; Java中的A ZipOutputStream允许您写入zip文件中的文件,而不必担心zip文件格式的内部问题。

您可能会发现的另一个常见问题是文本流,它允许您编写字符串的字节,或者某些语言​​提供的二进制流,允许您编写基本类型。您在文本流中发现的常见事项是字符编码,您应该知道这一点。

某些流也支持随机访问,例如this示例。另一方面,网络流出于显而易见的原因不会。

UNIX like操作系统也支持带有程序输入和输出的流模型,如所述。

5

除了上面提到的东西之外,还有一种不同类型的流 - 如函数式编程语言(如Scheme或Haskell)中定义的 - 一种可能无限的数据结构,由一些按需函数生成。

4

另一个比喻:你不能在流中游泳,这就是为什么你可以从流中取出下一位,字节,字符串或对象,而已经读取的数据被删除。单程票...或基本上只是一个队列没有存储持久性。

那么我们需要排队吗?你决定。

+0

这意味着,在一条河流中,你必须前进不能倒退。另外之前的数据被删除,因为你往前保存了内存? – 2016-03-08 07:05:30

3

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

开始思考与水流类比。您会收到持续的数据流,就像水在河中不断流动一样。你不一定知道数据来自哪里,大多数情况下你不需要;无论是来自文件,套接字还是其他来源,它都没有(不应该)真的很重要。这与接收水流非常相似,因此您不需要知道它来自哪里;无论是来自湖泊,喷泉还是任何其他来源,它都没有(不应该)真的很重要。 source