C# MemoryStream
last modified April 20, 2025
This tutorial explains how to use the MemoryStream class in C# for in-memory stream operations. MemoryStream provides a stream interface for working with data in memory.
The MemoryStream class creates a stream that uses memory as storage instead of a disk or network connection. It inherits from the Stream class.
MemoryStream
is useful when you need stream functionality but want
to avoid disk I/O. It's commonly used for temporary storage, data manipulation,
and as an intermediate buffer.
Basic MemoryStream Example
This example demonstrates creating a MemoryStream and writing some bytes to it. We then read the data back from the stream.
using System; using System.IO; using System.Text; class Program { static void Main() { // Create a MemoryStream using (MemoryStream stream = new MemoryStream()) { // Write data to the stream byte[] data = Encoding.UTF8.GetBytes("Hello MemoryStream!"); stream.Write(data, 0, data.Length); // Reset position to read from beginning stream.Position = 0; // Read data back byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); string text = Encoding.UTF8.GetString(buffer); Console.WriteLine(text); } } }
The example creates a MemoryStream, writes a string as bytes, then reads it back. The Position property is reset to 0 before reading to start from the beginning.
MemoryStream implements IDisposable, so we use it in a using statement. The stream automatically expands as needed when writing data. The example shows the basic write-read cycle that's common with MemoryStream operations.
Reading and Writing Primitive Types
MemoryStream can be used with BinaryWriter and BinaryReader to handle primitive data types. This example shows how to write and read different types.
using System; using System.IO; class Program { static void Main() { using (MemoryStream stream = new MemoryStream()) { // Write data using BinaryWriter using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) { writer.Write(42); writer.Write(3.14159); writer.Write(true); writer.Write("C# MemoryStream"); } // Reset position to read stream.Position = 0; // Read data using BinaryReader using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) { Console.WriteLine(reader.ReadInt32()); Console.WriteLine(reader.ReadDouble()); Console.WriteLine(reader.ReadBoolean()); Console.WriteLine(reader.ReadString()); } } } }
BinaryWriter and BinaryReader provide convenient methods for primitive types. The stream is passed to their constructors, leaving the stream open for further use.
Note the true parameter in the BinaryWriter/BinaryReader constructors. This keeps the stream open after the writer/reader is disposed. The data is written sequentially and must be read in the same order.
Converting MemoryStream to Byte Array
MemoryStream can easily convert its contents to a byte array. This example shows how to get the underlying byte array from a MemoryStream.
using System; using System.IO; using System.Text; class Program { static void Main() { // Create and write to MemoryStream using (MemoryStream stream = new MemoryStream()) { string text = "This will be converted to a byte array"; byte[] data = Encoding.UTF8.GetBytes(text); stream.Write(data, 0, data.Length); // Get the byte array byte[] byteArray = stream.ToArray(); Console.WriteLine($"Byte array length: {byteArray.Length}"); Console.WriteLine($"Content: {Encoding.UTF8.GetString(byteArray)}"); } } }
The ToArray method creates a new byte array containing the stream's data. This is useful when you need to pass the data to methods expecting byte arrays.
The example writes a string to the stream, then converts it to a byte array. The original stream remains unchanged. This operation is efficient as it directly accesses the internal buffer.
Using MemoryStream with StreamWriter/Reader
MemoryStream can work with text-oriented StreamWriter and StreamReader classes. This example demonstrates text-based operations.
using System; using System.IO; using System.Text; class Program { static void Main() { using (MemoryStream stream = new MemoryStream()) { // Write text using StreamWriter using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { writer.WriteLine("First line of text"); writer.WriteLine("Second line of text"); writer.Flush(); // Reset position to read stream.Position = 0; // Read text using StreamReader using (StreamReader reader = new StreamReader(stream, Encoding.UTF8, false, 1024, true)) { string line; while ((line = reader.ReadLine()) != null) { Console.WriteLine(line); } } } } } }
StreamWriter and StreamReader handle text encoding and provide line-based operations. The Flush call ensures all buffered data is written to the stream.
The example shows how to chain stream operations. The leaveOpen parameter is set to true to keep the MemoryStream available after the writer is disposed. This pattern is common when working with layered stream operations.
MemoryStream with Initial Capacity
MemoryStream can be initialized with a specific capacity to optimize performance. This example shows how to use the capacity constructor.
using System; using System.IO; class Program { static void Main() { // Create with initial capacity of 1KB using (MemoryStream stream = new MemoryStream(1024)) { Console.WriteLine($"Initial capacity: {stream.Capacity}"); // Write data until we exceed capacity byte[] data = new byte[512]; for (int i = 0; i < 5; i++) { stream.Write(data, 0, data.Length); Console.WriteLine($"Capacity after write {i+1}: {stream.Capacity}"); } } } }
Setting an initial capacity can prevent unnecessary reallocations. The stream will automatically expand when needed, but this has performance overhead.
The example shows how the capacity grows as data is written. The initial capacity is 1024 bytes. After writing 2.5KB of data, the capacity has doubled to accommodate the new data. This demonstrates the automatic resizing behavior.
MemoryStream as Buffer for Network Operations
MemoryStream is often used as a buffer for network operations. This example simulates receiving chunks of data and assembling them in a MemoryStream.
using System; using System.IO; using System.Text; class Program { static void Main() { // Simulate receiving data chunks byte[][] chunks = { Encoding.UTF8.GetBytes("This is "), Encoding.UTF8.GetBytes("a multi-chunk "), Encoding.UTF8.GetBytes("message assembled "), Encoding.UTF8.GetBytes("in MemoryStream") }; using (MemoryStream stream = new MemoryStream()) { // Process each chunk foreach (byte[] chunk in chunks) { Console.WriteLine($"Processing {chunk.Length} byte chunk"); stream.Write(chunk, 0, chunk.Length); } // Get complete message stream.Position = 0; using (StreamReader reader = new StreamReader(stream)) { Console.WriteLine("Complete message:"); Console.WriteLine(reader.ReadToEnd()); } } } }
MemoryStream is ideal for assembling data from multiple sources. It provides the flexibility to write data as it arrives and read it when complete.
The example simulates receiving data in chunks over a network. Each chunk is written to the MemoryStream as it arrives. Finally, the complete message is read from the stream. This pattern is common in network programming.
MemoryStream for Image Manipulation
MemoryStream is commonly used with image processing. This example shows how to load an image into a MemoryStream and then save it to a file.
using System; using System.IO; using System.Drawing; class Program { static void Main() { // Load an image file into MemoryStream byte[] imageBytes = File.ReadAllBytes("input.jpg"); using (MemoryStream stream = new MemoryStream(imageBytes)) { // Process the image in memory using (Image image = Image.FromStream(stream)) { Console.WriteLine($"Image size: {image.Width}x{image.Height}"); // Save to a new file (simulating processing) image.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); } } Console.WriteLine("Image processed and saved"); } }
MemoryStream allows image processing without multiple disk operations. The image is loaded once into memory and can be processed efficiently.
The example reads an image file into a byte array, then creates a MemoryStream from it. The Image class can load directly from the stream. This approach is useful when working with images from databases or network sources.
Source
MemoryStream Class Documentation
This tutorial covered using MemoryStream in C# for various scenarios including basic operations, primitive types, text handling, buffering, and image processing.
Author
List all C# tutorials.