您能解释一的概念吗?
我知道流是字节序列的表示形式。每个流都提供将字节读取和写入其给定后备存储的方法。但是,流有什么意义呢?为什么后备商店本身不是我们与之交互的内容?
无论出于何种原因,这个概念对我来说都不是点击。我读过一堆文章,但我认为我需要一个类比或其他东西。
我知道流是字节序列的表示形式。每个流都提供将字节读取和写入其给定后备存储的方法。但是,流有什么意义呢?为什么后备商店本身不是我们与之交互的内容?
无论出于何种原因,这个概念对我来说都不是点击。我读过一堆文章,但我认为我需要一个类比或其他东西。
之所以选择“流”这个词,是因为它代表了(在现实生活中)与我们使用它时想要传达的含义非常相似的含义。
让我们暂时忘记后备商店,开始考虑与水流的类比。您会收到连续的数据流,就像水在河流中连续流动一样。你不一定知道数据来自哪里,而且大多数情况下你不需要;无论是来自文件,套接字还是任何其他来源,它都不是(不应该)真正重要的。这与接收水流非常相似,因此您不需要知道它来自哪里;无论是来自湖泊,喷泉还是任何其他来源,它都不是(不应该)真正重要的。
也就是说,一旦你开始认为你只关心获取你需要的数据,无论它来自哪里,其他人谈论的抽象就会变得更加清晰。您开始认为可以包装流,并且您的方法仍然可以完美地工作。例如,您可以执行以下操作:
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());
看?只要您的方法不关心输入源是什么,您就可以以各种方式自定义源。抽象允许您以非常优雅的方式将输入与处理逻辑分离。
请注意,我们自己创建的流没有后备商店,但它仍然完美地满足了我们的目的。
因此,总而言之,流只是输入的来源,隐藏(抽象)另一个来源。只要你不破坏抽象,你的代码就会非常灵活。
关键是你不应该知道后备商店是什么 - 这是对它的抽象。事实上,甚至可能没有后备存储 - 您可能正在从网络读取,并且数据永远不会被“存储”。
如果你可以编写有效的代码,无论你是与文件系统、内存、网络还是其他任何支持流思想的东西通信,那么你的代码就会更加灵活。
此外,流通常链接在一起 - 您可以有一个流来压缩放入其中的任何内容,将压缩的形式写入另一个流,或者加密数据的流,等等。在另一端会有反向链,解密,解压缩或其他什么。