Java 你能解释一下流的概念吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/507747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:32:06  来源:igfitidea点击:

Can you explain the concept of streams?

java.netstreamlanguage-agnosticiostream

提问by Rob Sobers

I understand that a stream is a representation of a sequence of bytes. Each stream provides means for reading and writing bytes to its given backing store. But what is the point of the stream? Why isn't the backing store itself what we interact with?

我知道流是字节序列的表示。每个流都提供了将字节读取和写入其给定后备存储的方法。但是流的重点是什么?为什么后备存储本身不是我们与之交互的?

For whatever reason this concept just isn't clicking for me. I've read a bunch of articles, but I think I need an analogy or something.

无论出于何种原因,这个概念并不适合我。我读了一堆文章,但我想我需要一个类比什么的。

采纳答案by Hosam Aly

The word "stream" has been chosen because it represents (in real life) a very similar meaning to what we want to convey when we use it.

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

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.

让我们暂时忘记后备存储,并开始考虑与水流的类比。您会收到源源不断的数据流,就像河流中不断流淌的水一样。您不一定知道数据来自哪里,而且大多数情况下您不需要知道;无论是来自文件、套接字还是任何其他来源,它都(不应该)真正重要。这与接收水流非常相似,您无需知道它来自哪里;无论是来自湖泊、喷泉还是任何其他来源,它都(不应该)真正重要。

That said, once you start thinking that you only care about getting the data you need, regardless of where it comes from, the abstractions other people talked about become clearer. You start thinking that you can wrap streams, and your methods will still work perfectly. For example, you could do this:

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

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

As you see, it becomes very easy to change your input source without changing your processing logic. For example, to read your data from a network socket instead of a file:

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

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

As easy as it can be. And the beauty continues, as you can use any kind of input source, as long as you can build a stream "wrapper" for it. You could even do this:

尽可能简单。美还在继续,因为您可以使用任何类型的输入源,只要您可以为其构建流“包装器”。你甚至可以这样做:

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

See? As long as your method doesn't care what the input source is, you can customize your source in various ways. The abstraction allows you to decouple input from processing logic in a very elegant way.

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

Note that the stream we created ourselves does not have a backing store, but it still serves our purposes perfectly.

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

So, to summarize, a stream is just a source of input, hiding away (abstracting) another source. As long as you don't break the abstraction, your code will be very flexible.

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

回答by Torlack

The point of the stream is to provide a layer of abstraction between you and the backing store. Thus a given block of code that uses a stream need not care if the backing store is a disk file, memory, etc...

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

回答by vava

It's just a concept, another level of abstraction that makes your life easier. And they all have common interface which means you can combine them in a pipe like manner. For example, encode to base64, then zip and then write this to disk and all in one line!

这只是一个概念,另一个抽象层次,让您的生活更轻松。而且它们都有通用的接口,这意味着您可以将它们组合成类似管道的方式。例如,编码为 base64,然后压缩,然后将其写入磁盘,全部在一行中完成!

回答by Jon Skeet

The point is that you shouldn't have to know what the backing store is - it's an abstraction over it. Indeed, there might not even bea backing store - you could be reading from a network, and the data is never "stored" at all.

关键是您不必知道后备存储是什么 - 它是对它的抽象。事实上,甚至可能不会一个后备存储-你可以从网络上阅读,而数据永远不会“存储”在所有。

If you can write code that works whether you're talking to a file system, memory, a network or anything else which supports the stream idea, your code is a lot more flexible.

如果您可以编写适用于文件系统、内存、网络或任何其他支持流思想的代码,那么您的代码将更加灵活。

In addition, streams are often chained together - you can have a stream which compresses whatever is put into it, writing the compressed form on to another stream, or one which encrypts the data, etc. At the other end there'd be the reverse chain, decrypting, decompressing or whatever.

此外,流通常链接在一起 - 您可以有一个流来压缩放入其中的任何内容,将压缩形式写入另一个流,或者加密数据等。在另一端会有相反的链,解密,解压缩或其他。

回答by Sean

A stream is an abstracting of a sequence of bytes. The idea is that you don't need to know where the bytes come from, just that you can read them in a standardized manner.

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

For example, if you process data via a stream then it doesn't matter to your code if the data comes from a file, a network connection, a string, a blob in a database etc etc etc.

例如,如果您通过流处理数据,那么数据是否来自文件、网络连接、字符串、数据库中的 blob 等,对您的代码来说并不重要。

There's nothing wrong per-se with interacting with the backing store itself except for the fact that it ties you to the backing store implementation.

与后备存储本身交互本身并没有错,除了它将您与后备存储实现联系起来的事实。

回答by Anton Gogolev

Think of streams as of an abstract source of data (bytes, characters, etc.). They abstract actual mechanics of reading from and writing to the concrete datasource, be it a network socket, file on a disk or a response from the web server.

将流视为抽象的数据源(字节、字符等)。它们抽象了读取和写入具体数据源的实际机制,无论是网络套接字、磁盘上的文件还是来自 Web 服务器的响应。

回答by Jeff Yates

A stream is an abstraction that provides a standard set of methods and properties for interacting with data. By abstracting away from the actual storage medium, your code can be written without total reliance on what that medium is or even the implementation of that medium.

流是一种抽象,它提供了一组用于与数据交互的标准方法和属性。通过从实际存储介质中抽象出来,您的代码可以在不完全依赖该介质是什么甚至该介质的实现的情况下编写。

An good analogy might be to consider a bag. You don't care what a bag is made of or what it does when you put your stuff in it, as long as the bag performs the job of being a bag and you can get your stuff back out. A stream defines for storage media what the concept of bag defines for different instances of a bag (such as trash bag, handbag, rucksack, etc.) - the rules of interaction.

一个很好的类比可能是考虑一个包。你不在乎袋子是由什么制成的,或者当你把东西放进去时它会做什么,只要袋子能起到袋子的作用,你可以把你的东西拿出来。流为存储介质定义了包的概念为包的不同实例(例如垃圾袋、手提包、背包等)定义了什么——交互规则。

回答by dmajkic

It's not about streams - it's about swimming. If you can swim one Stream, than you can swim any Stream you encounter.

这不是关于溪流——而是关于游泳。如果你能游过一条溪流,那么你就可以游过你遇到的任何一条溪流。

回答by Julian Birch

I think you need to consider that the backing store itself is often just another abstraction. A memory stream is pretty easy to understand, but a file is radically different depending on which file system you're using, never mind what hard drive you are using. Not all streams do in fact sit on top of a backing store: network streams pretty much just are streams.

我认为您需要考虑后备存储本身通常只是另一种抽象。内存流很容易理解,但是根据您使用的文件系统,文件完全不同,更不用说您使用的硬盘驱动器了。并非所有流实际上都位于后备存储之上:网络流几乎只是流。

The point of a stream is that we restrict our attention to what is important. By having a standard abstraction, we can perform common operations. Even if you don't want to, for instance, search a file or an HTTP response for URLs today, doesn't mean you won't wish to tomorrow.

流的重点是我们将注意力限制在重要的事情上。通过拥有标准抽象,我们可以执行常见操作。例如,即使您今天不想在文件或 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.

流最初是在内存与存储相比很小的时候构思出来的。仅仅读取一个 C 文件可能是一个很大的负担。最大限度地减少内存占用非常重要。因此,一个不需要加载的抽象非常有用。今天,它在执行网络通信时同样有用,而且事实证明,在我们处理文件时很少有这种限制。以一般方式透明地添加诸如缓冲之类的东西的能力使其更加有用。

回答by OwenP

To add to the echo chamber, the stream is an abstraction so you don't care about the underlying store. It makes the most sense when you consider scenarios with and without streams.

添加到回声室,流是一个抽象,所以你不关心底层存储。当您考虑有和没有流的场景时,这是最有意义的。

Files are uninteresting for the most part because streams don't do much above and beyond what non-stream-based methods I'm familiar with did. Let's start with internet files.

文件在很大程度上是无趣的,因为流除了我熟悉的基于非流的方法所做的之外,并没有做太多的事情。让我们从互联网文件开始。

If I want to download a file from the internet, I have to open a TCP socket, make a connection, and receive bytes until there are no more bytes. I have to manage a buffer, know the size of the expected file, and write code to detect when the connection is dropped and handle this appropriately.

如果我想从 Internet 下载文件,我必须打开一个 TCP 套接字,建立连接并接收字节,直到没有更多字节为止。我必须管理一个缓冲区,知道预期文件的大小,并编写代码来检测连接何时断开并适当处理。

Let's say I have some sort of TcpDataStream object. I create it with the appropriate connection information, then read bytes from the stream until it says there aren't any more bytes. The stream handles the buffer management, end-of-data conditions, and connection management.

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

In this way, streams make I/O easier. You could certainly write a TcpFileDownloader class that does what the stream does, but then you have a class that's specific to TCP. Most stream interfaces simply provide a Read() and Write() method, and any more complicated concepts are handled by the internal implementation. Because of this, you can use the same basic code to read or write to memory, disk files, sockets, and many other data stores.

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