A stream is an abstraction over a sequence of bytes. You can think of it as a continuous buffer that can be read or written. Streams are often used in conjunction with buffers to help load data into memory more efficiently. The System.IO namespace in .NET has many classes that work with streams, such as the FileStream, MemoryStream, FileInfo, and StreamReader/Writer classes.
Basically, streams are categorized as byte streams or character streams, where byte streams deal with data represented as bytes and character streams deal with characters. In .NET, byte streams include the Stream, FileStream, MemoryStream, and BufferedStream classes. .NET character streams include TextReader, TextWriter, StreamReader, and StreamWriter.
This article demonstrates the use of the BufferedStream and MemoryStream classes in C#, with relevant code examples where available. To work with the code samples provided in this article, you must have Visual Studio 2022 installed on your system. If you don’t already have a copy, you can download Visual Studio 2022 here.
Create a Console Application Project in Visual Studio
First, let’s create a .NET Core console app project in Visual Studio. Assuming you have Visual Studio 2022 installed on your system, follow the steps outlined below to create a new .NET Core Console Application project in Visual Studio.
- Launch the Visual Studio IDE.
- Click on “Create a new project”.
- In the “Create a new project” window, select “Console application (.NET Core)” from the list of templates displayed.
- Click Next.
- In the “Set up your new project” window shown below, specify the name and location of the new project.
- Click Next.
- In the “Additional Information” window displayed next, choose “.NET 7.0 (Standard Term Support)” as the Framework version you wish to use.
- Click Create.
We will use this .NET 7 console application project to work with the BufferedStream and MemoryStream classes in later sections of this article.
What is a stamp?
A buffer represents a block of bytes in memory where you can temporarily store transient data. A buffer helps minimize the number of calls your application makes to read and write data to and from the file system. Buffers are useful when you need to store data that is transferred from one computer system to another or from one program component to another.
Buffers are used in conjunction with streams to facilitate efficient reading and writing of data by programs. Buffers temporarily store data so that your application does not need to re-read data from disk each time it is requested.
Use BufferedStream class in C#
The BufferedStream class represents a type of stream that can buffer data before writing it to the stream. In other words, a buffered stream can read or write data to a buffer, allowing you to read or write larger blocks of data at a time to improve performance. You can create buffered streams from memory streams and file streams.
When you create an instance of the BufferedStream class, you can also specify the buffer size. The default buffer size is 4096 bytes. Reading data from a buffered stream involves reading from the buffer when you call the Read method. Even if you call Read multiple times, the data will only be retrieved from the stream once.
When you write to a buffered stream, data is written to a buffer and then flushed to the stream when you call the Flush method. This improves performance by avoiding accessing the stream for each Write call. When we use a buffer, we do not perform any writes or reads until a certain number of operations have been requested.
By storing a certain amount of data in its internal buffer, BufferedStream can process multiple operations on the same piece of memory without having to allocate memory over and over again. This saves time and memory when repeatedly creating new objects.
Note that you can use a BufferedStream instance to read or write data, but you cannot use the same instance for both operations. BufferedStream is designed to prevent input and output from slowing down when there is no need for a buffer. A buffered stream may not even allocate an internal buffer if the read and write size is always greater than the internal buffer size.
The following code snippet shows how you can write data to a file using BufferedStream.
using (FileStream fileStream = new FileStream("D:\\MyTextFile.txt", FileMode.Create, FileAccess.ReadWrite))
{
BufferedStream bufferedStream = new BufferedStream(fileStream, 1024);
byte[] bytes = Encoding.ASCII.GetBytes("This is a sample text.");
bufferedStream.Write(bytes);
bufferedStream.Flush();
bufferedStream.Close();
}
When to use BufferedStream? Use BufferedStream when you want to add buffering support to an existing stream. So, if the original stream was a network stream, data sent to it would be cached in a small buffer before being written to or retrieved from the network stream.
Using MemoryStream class in C#
The MemoryStream class represents a lightweight stream that lets you write to or read from a buffer. The MemoryStream class supports the same methods and properties as those of the Stream class. MemoryStream provides an easy way to read or write data directly from memory, without having to allocate and free memory each time you want to read or write something. This makes it faster than using other techniques that require you to reallocate memory each time you use it.
A memory stream is a very fast and efficient stream since the data resides in memory. However, this also means that it can be easily lost if the program crashes or the computer suddenly shuts down.
The MemoryStream class is part of the System.IO namespace. It can be used to read and write to files, network connections, and other devices that support reading and writing data. The MemoryStream class can also be used to serialize an object into a stream of bytes for storage or transmission over a network connection.
The following code snippet shows how you can write data to a memory stream in C#.
byte[] bytes = System.Text.Encoding.ASCII.GetBytes("This is a sample text.");
using (MemoryStream memoryStream = new MemoryStream(50))
{
memoryStream.Write(bytes, 0, bytes.Length);
}
When to use MemoryStream? As the name suggests, MemoryStream is a memory-only stream. As such, it should only be used when the amount of data to be cached is small enough to fit comfortably in memory.
While BufferedStream is faster and more efficient, MemoryStream is well suited for scenarios where your application requires faster data access. You can use the asynchronous versions of the Read and Write methods of the BufferedStream and MemoryStream classes for even better performance and scalability.
Copyright © 2022 IDG Communications, Inc.