我理解流是字节序列的表示。每个流都提供了将字节读写到其给定的后备存储的方法。但溪流的意义何在?为什么后台存储本身不是我们交互的对象?

不知什么原因,我就是不喜欢这个概念。我读了很多文章,但我觉得我需要一个类比。


当前回答

另一点(对于读取文件的情况):

流可以允许您在完成读取文件的所有内容之前执行其他操作。 可以节省内存,因为不需要一次加载所有文件内容。

其他回答

我认为您需要考虑后备存储本身通常只是另一种抽象。内存流很容易理解,但是文件完全不同,这取决于您使用的文件系统,而不考虑您使用的是什么硬盘驱动器。事实上,并不是所有的流都位于备份存储的顶部:网络流基本上就是流。

流的意义在于我们将注意力限制在重要的事情上。通过标准抽象,我们可以执行公共操作。例如,即使您今天不想在文件或HTTP响应中搜索url,也不意味着您明天就不想这样做了。

Streams were originally conceived when memory was tiny compared to storage. Just reading a C file could be a significant load. Minimizing the memory footprint was extremely important. Hence, an abstraction in which very little needed to be loaded was very useful. Today, it is equally useful when performing network communication and, it turns out, rarely that restrictive when we deal with files. The ability to transparently add things like buffering in a general fashion makes it even more useful.

之所以选择“流”这个词,是因为它(在现实生活中)与我们使用它时想要传达的意思非常相似。

Start thinking about the analogy to a water stream. You receive a continuous flow of data, just like water continuously flows in a river. You don't necessarily know where the data is coming from, and most often you don't need to; be it from a file, a socket, or any other source, it doesn't (shouldn't) really matter. This is very similar to receiving a stream of water, whereby you don't need to know where it is coming from; be it from a lake, a fountain, or any other source, it doesn't (shouldn't) really matter. source

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

In languages such as C#, VB.Net, C++, Java etc., the stream metaphor is used for many things. There are file streams, in which you open a file and can read from the stream or write to it continuously; There are network streams where reading from and writing to the stream reads from and writes to an underlying established network connection. Streams for writing only are typically called output streams, as in this example, and similarly, streams that are for reading only are called input streams, as in this example.

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

您可能会发现的另一个常见的东西是允许您编写字符串而不是字节的文本流,或者一些语言提供了允许您编写基本类型的二进制流。您将在文本流中发现一个常见的东西是字符编码,您应该知道这一点。

一些流还支持随机访问,如本例所示。另一方面,由于显而易见的原因,网络流不会。

MSDN很好地概述了。net中的流。 Sun还概述了他们的通用OutputStream类和InputStream类。 在c++中,这里有istream(输入流),ostream(输出流)和iostream(双向流)文档。

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

之所以选择“流”这个词,是因为它(在现实生活中)与我们使用它时想要传达的意思非常相似。

Let's forget about the backing store for a little, and start thinking about the analogy to a water stream. You receive a continuous flow of data, just like water continuously flows in a river. You don't necessarily know where the data is coming from, and most often you don't need to; be it from a file, a socket, or any other source, it doesn't (shouldn't) really matter. This is very similar to receiving a stream of water, whereby you don't need to know where it is coming from; be it from a lake, a fountain, or any other source, it doesn't (shouldn't) really matter.

也就是说,一旦您开始认为您只关心获得所需的数据,而不管数据来自何处,其他人谈论的抽象概念就会变得更加清晰。您开始认为可以包装流,并且您的方法仍然可以完美地工作。例如,你可以这样做:

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

看到了吗?只要您的方法不关心输入源是什么,您就可以以各种方式自定义源。抽象允许您以一种非常优雅的方式将输入与处理逻辑解耦。

请注意,我们自己创建的流没有备份存储,但它仍然完美地满足了我们的目的。

所以,总的来说,流只是一个输入源,隐藏(抽象)了另一个源。只要你不打破抽象,你的代码就会非常灵活。

流是字节序列的抽象。其思想是,您不需要知道字节来自何处,只需以标准化的方式读取它们。

例如,如果你通过流处理数据,那么数据来自文件、网络连接、字符串、数据库中的blob等等,对你的代码来说都无关紧要。

与备份存储本身交互本身并没有什么问题,除了它将您绑定到备份存储实现。