10.1 Streams and Backing Stores
The stream is a fundamental abstraction used throughout the .NET
Framework to model access to persistent data. A stream represents the
flow of data coming in and out of a backing store. A backing store
represents the endpoint of a stream. Although a backing store is
often a file or network connection, in reality it can represent any
medium capable of reading or writing raw data.
A simple example is to use a stream to read and write to a file on
disk. However, streams and backing stores are not limited to disk and
network I/O. A more sophisticated example is to use the cryptography
support in the .NET Framework to encrypt or decrypt a stream of bytes
as they move around in memory.
10.1.1 The Abstract Stream Class
Stream is an abstract class that defines
operations
for reading and writing a stream of raw typeless data as bytes. Once
a stream is opened, it stays open and can be read from or written to
until the stream is flushed and closed. Flushing a stream updates the
writes made to the stream; closing a stream first flushes the stream,
then closes the stream.
Stream has the
methods CanRead,
CanWrite, and CanSeek, for
streams that support only sequential access. If a stream supports
random access, the SetPosition method can move to
a linear position on that stream.
The Stream class provides
synchronous and asynchronous read and write operations. By default,
an asynchronous method calls the stream's
corresponding synchronous method by wrapping the synchronous method
in a delegate type and starting a new thread. Similarly, by default,
a synchronous method calls the stream's
corresponding asynchronous method and waits until the thread has
completed its operation. Classes that derive from
Stream must override either the synchronous or
asynchronous methods but may override both sets of methods if the need
arises.
10.1.2 Concrete Stream-Derived Classes
The framework includes a
number of different concrete
implementations of the abstract base class Stream.
Each implementation represents a different storage medium and allows
a raw stream of bytes to be read from and written to the backing
store.
Examples of this include
the
FileStream class (which reads and writes bytes to
and from a file), the NetworkStream
class
(which sends and receives bytes over the network), and the stream
returned from the static Stream.Null property
(which serves as /dev/null for this platform).
The following example creates a text file on disk and uses the
abstract File type to write data to it:
using System.IO;
class StreamFun {
static void Main( ) {
Stream s = new FileStream("foo.txt", FileMode.Create);
s.WriteByte(67);
s.WriteByte(35);
s.Close( );
}
}
In addition, one stream may act as the frontend to another stream,
performing additional processing on the underlying stream as needed.
Examples of this include stream encryption/decryption and stream
buffering.
The following is an example that converts the file output from the
previous sample into its Base64 representation using the
CryptoStream class:
using System;
using System.IO;
using System.Security.Cryptography;
class EncoderFun {
static void Main( ) {
Stream stm = new FileStream("foo.txt", FileMode.Open, FileAccess.Read);
ICryptoTransform ict = new ToBase64Transform( );
CryptoStream cs = new CryptoStream(stm, ict, CryptoStreamMode.Read);
TextReader tr = new StreamReader(cs);
string s = tr.ReadToEnd( );
Console.WriteLine(s);
}
}
|