When you first start learning VB.NET, one of the first things you may notice is the absence of "traditional" file I/O support in .NET. Microsoft has replaced the classic IO operations by stream operations. A stream is a simple concept that originated in the Unix world.
You can think of stream as a channel through which data flows from your application to a sequential data store (such as a file, a string, a byte array, or another stream), or vice versa. To understand why the traditional file I/O operations were replaced by streams, you must consider that not all data reside in files. Modern applications acquire data from many different data stores, including files, in-memory buffers and the Internet. The stream analogy enables applications to access all these data stores with the same programming model. There's no need to learn how to use Sockets to access a file on a remote Web server. You can establish a stream between your application and a remote resource and read the bytes as the server sends them.
A stream encapsulates all the operations you can perform against a data store. The big advantage is that after you learn how to deal with streams for one data source, you can apply the same techniques to widely differing data sources. This article primarily focuses on using streams with files, but you'll see a few examples of using streams with other data stores, such as resources on a remote server, toward the end of this article.
Types of Streams
The Stream class is abstract; you can't declare a new instance of type Stream in your code. There are five classes in the .NET Framework that derive from the Stream class. These are:
- FileStream. Supports sequential and random access to files
- MemoryStream. Supports sequential and random access to memory buffers
- NetworkStream. Supports sequential access to Internet resources. The NetworkStream resides in the System.Net.Sockets namespace.
- CryptoStream. Supports data encryption and decryption. The CryptoStream resides in the System.Security.Cryptography namespace.
- BufferedStream. Supports buffered access to stream that do not support buffering on their own
Not all streams support exactly the same operations. A stream for reading a local file, for example, can report the length of the file and the current position in the file, with the Length
properties, respectively. You can jump to any location in the file with the Seek
method. In contrast, a stream for reading a remote file doesn't support those features. But the stream classes help you differentiate Streams programmatically, by providing CanSeek
properties. Despite some data-store-dependent differences, the basic methods of all Stream classes let you write data to or read data from the underlying data store.