Streams
A stream is an abstraction for reading or writing data sequentially, as a flow of bytes, without holding all of it in memory. File.ReadAllBytes loads a whole file at once, which fails for a huge file or for data with no end, like a socket. A stream gives one buffer at a time.
using var stream = File.OpenRead("huge_video.mp4");byte[] buffer = new byte[4096];int bytesRead;while ((bytesRead = await stream.ReadAsync(buffer)) > 0){ ProcessChunk(buffer, bytesRead); // work with 4KB at a time, not 40GB}One interface, many sources
Stream is a base class with the same Read and Write for every source: FileStream, NetworkStream, MemoryStream, GZipStream and CryptoStream (which wrap another stream), and the body of an HttpResponseMessage. Wrapping composes them, such as a FileStream inside a GZipStream, which is the Decorator patternStructural patternsFour patterns for composing classes and objects into larger structures.Opens in a new tab.
Async
ReadAsync is genuine async I/O: if data isn’t ready, the thread is freed (see how await worksHow await works under the hoodThe compiler turns an async method into a state machine, and the thread is freed while it waits.Opens in a new tab). Read blocks the calling thread, so most Stream methods have both forms. A method that does real stream I/O is I/O-bound (see CPU or I/OIs this library method CPU-bound or I/O-bound?The Async suffix does not say. Six checks, in order of effort.Opens in a new tab).
Where it matters
Reading pulls bytes out and writing pushes bytes in. A stream is not the data but a sequential window onto it, and the primitive that non-blocking I/O is built on.