8

How to Convert Stream to Byte Array in C#

 1 year ago
source link: https://code-maze.com/create-byte-array-from-stream-in-csharp/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

How to Convert Stream to Byte Array in C#

Posted by Januarius Njoku | Updated Date May 22, 2023 | 0

Code Maze Book Collection

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API program and learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

In this article, we are going to learn how to convert a stream to a byte array in C#.

To download the source code for this article, you can visit our GitHub repository.

A Stream represents a continuous flow of data that a reader or writer can sequentially access. This access is typically byte by byte or in blocks of bytes. In C#, the Stream class is an abstract class that provides a generic view of a sequence of bytes. To learn more about the Stream class, please visit How to Use MemoryStream in C#.

In this article, we will explore five ways of converting a stream to a byte array. Additionally, we will perform benchmark tests to evaluate the speed and memory usage of all the methods.

Let’s dive in.

Preparation of Data Source

To begin, let’s add a text file to our project:

According to a report by ZGSMA, the mobile industry in Zootopia has seen
mobile broadband connections grew from 10% in 2000 to 74% in 2023.
According to a report by ZGSMA, the mobile industry in Zootopia has seen 
mobile broadband connections grew from 10% in 2000 to 74% in 2023.

Now, let’s use this file to create a FileStream object:

private static readonly string _sampleFilePath
= Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName, "samplefile.txt");
private readonly FileStream _stream
= new(_sampleFilePath, FileMode.Open, FileAccess.Read);
private static readonly string _sampleFilePath
    = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName, "samplefile.txt");

private readonly FileStream _stream
    = new(_sampleFilePath, FileMode.Open, FileAccess.Read);

We aim to implement methods that convert _stream to a byte array.

Convert Stream to Byte Array With the Stream Class

First, let’s explore how to convert a stream to a byte array using the Read() method from the Stream class.

The Stream.Read() method, may not always read all the data we ask it to read. For instance, if we’re reading data from a file stream, the Read() method may only read a section of the file and return it, even if we expect more data.

To ensure that we accurately read and convert all the data in the stream with the Stream.Read() method, we can create a method that reads and copies the data repeatedly until there is no more data left to be read:

public byte[] UseStreamDotReadMethod(Stream stream)
byte[] bytes;
List<byte> totalStream = new();
byte[] buffer = new byte[32];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
totalStream.AddRange(buffer.Take(read));
bytes = totalStream.ToArray();
return bytes;
public byte[] UseStreamDotReadMethod(Stream stream)
{
    byte[] bytes;
    List<byte> totalStream = new();
    byte[] buffer = new byte[32];
    int read;

    while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
    {
        totalStream.AddRange(buffer.Take(read));
    }

    bytes = totalStream.ToArray();

    return bytes;
}

In this method, we start by initializing totalStream, a List<byte> object, and a buffer array of bytes with a size of 32.

Next, we define read, an integer variable that will store the number of bytes read from the stream. Then we use a while loop to repeatedly read data from the stream into the buffer array until no more bytes are left to read.

Inside the while loop, we check the value of the read variable. If it is greater than zero, we add the bytes that were read to the totalStream list using the AddRange() method, which concatenates two lists of bytes. We use the Take() method to select only the number of bytes read and avoid adding empty bytes to our totalStream list.

Finally, we return the contents of the totalStream list as a byte array using the ToArray() method.

Convert Stream to Byte Array With the BinaryReader Class

An easier way of converting a stream to a byte array in C#, is by using the BinaryReader class. This class allows us to read binary data from a stream and convert it into a byte array. Unlike the Stream.Read() method, the BinaryReader.Read() method will keep reading the data until the end of the stream once we specify the size to start with.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

To see how this works, let’s create a UseBinaryReader() method:

public byte[] UseBinaryReader(Stream stream)
byte[] bytes;
using (var binaryReader = new BinaryReader(_stream))
bytes = binaryReader.ReadBytes((int)stream.Length);
return bytes;
public byte[] UseBinaryReader(Stream stream)
{
    byte[] bytes;

    using (var binaryReader = new BinaryReader(_stream))
    {
        bytes = binaryReader.ReadBytes((int)stream.Length);
    }

    return bytes;
}

Here, we instantiate a BinaryReader object with the stream we want to read from. Next, we use the ReadBytes() method of the BinaryReader class to read the bytes from the stream and convert them into a byte array.

The ReadBytes() method takes an integer parameter that specifies the number of bytes to read from the stream. In this case, we aim to read all the bytes in the stream. Therefore, we pass in the length of the stream as an argument.

Finally, we return the byte array containing the data from the stream.

Convert Stream to Byte Array With the StreamReader Class

Alternatively, we can convert a stream to a byte array with the StreamReader class. This class allows us to easily read textual data from a stream and convert it to a byte array.

To use the StreamReader class for this purpose, let’s define a UseStreamReader() method:

public byte[] UseStreamReader(Stream stream)
byte[] bytes;
using (var reader = new StreamReader(stream))
bytes = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
return bytes;
public byte[] UseStreamReader(Stream stream)
{
    byte[] bytes;

    using (var reader = new StreamReader(stream))
    {
        bytes = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
    }

    return bytes;
}

First, we create an instance of the StreamReader class and pass in the original stream as an argument. Then, we call the ReadToEnd() method on the reader object to read all the data from the stream as a string.

Finally, we use the GetBytes() method of the UTF8 encoding class to convert the string to a byte array and return it to the caller.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

It is important to note that this method assumes that the stream contains textual data encoded in UTF8. If the data is in a different encoding, we should use the corresponding encoding class instead of UTF8.

Convert Stream to Byte Array With the MemoryStream Class

Additionally, we can use the MemoryStream class to convert streams to byte arrays. This class provides an efficient approach for handling memory usage during the conversion, especially when working with large data streams.

To achieve this, the MemoryStream class buffers data in small portions. This action helps to prevent unnecessary memory allocation and reduce the memory required for the operation. As a result, this approach reduces the frequency of garbage collection, leading to an overall improvement in the process’s performance.

With this in mind, let’s define a UseMemoryStream() method:

public byte[] UseMemoryStream(Stream stream)
byte[] bytes;
if (_stream is MemoryStream memStream)
return memStream.ToArray();
using (var memoryStream = new MemoryStream())
stream.CopyTo(memoryStream);
bytes = memoryStream.ToArray();
return bytes;
public byte[] UseMemoryStream(Stream stream)
{
    byte[] bytes;

    if (_stream is MemoryStream memStream)
    {
        return memStream.ToArray();
    }

    using (var memoryStream = new MemoryStream())
    {
        stream.CopyTo(memoryStream);
        bytes = memoryStream.ToArray();
    }

    return bytes;
}

Here, we use an if statement to check if the stream we want to convert is already a MemoryStream. If it is, we call the ToArray() method on the stream and return the resulting byte array.

However, if the stream is not a MemoryStream, we create a new instance of the MemoryStream class. Then, we use the CopyTo() method to copy the contents of the original stream into the memory stream. Subsequently, we invoke the ToArray() method on the memory stream to get the byte array representation of the stream.

Convert Stream to Byte Array With the BufferedStream Class

Now, let’s explore another method that involves using the BufferedStream class.

The BufferedStream class provides a way to improve the performance of a stream by incorporating a buffer.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

We use a buffer to temporarily store data when transferring between components in a computer system with different speeds. This momentary storage enhances data processing and transfer efficiency by decreasing the number of calls between the system’s components. When converting a stream to a byte array, a buffer reduces the overall time for reading from the stream.

To use the BufferedStream class to convert a stream to a byte array, let’s start by defining a method:

public byte[] UseBufferedStream(Stream stream)
byte[] bytes;
using (var bufferedStream = new BufferedStream(stream))
using var memoryStream = new MemoryStream();
bufferedStream.CopyTo(memoryStream);
bytes = memoryStream.ToArray();
return bytes;
public byte[] UseBufferedStream(Stream stream)
{
    byte[] bytes;

    using (var bufferedStream = new BufferedStream(stream))
    {
        using var memoryStream = new MemoryStream();
        bufferedStream.CopyTo(memoryStream);
        bytes = memoryStream.ToArray();
    }

    return bytes;
}

First and foremost, we declare a variable to hold the data we will convert. We then create an instance of the BufferedStream class and pass in the original stream as an argument.

Next, we define a MemoryStream object to write the data we read from the BufferedStream object. To transfer the data between the two streams, we use the CopyTo() method on the BufferedStream object and pass in the MemoryStream object as an argument.

This transfer is necessary because when working with a BufferedStream, we store the data in a buffer, and write or read from the underlying stream only in packets, as needed. Therefore, to convert the contents of the BufferedStream to a byte[] array, we must first copy the buffered data to an intermediate buffer, such as a MemoryStream, and then convert it to a byte array.

Finally, we invoke the ToArray() method on the MemoryStream object to retrieve the data as a byte array and return it to the caller.

What’s the Fastest Way to Convert a Stream to Byte Array in C#?

Now that all our methods are ready, we can evaluate their time and memory performance using the BenchmarkDotNet library. To view the benchmark implementation, please refer to this file//GitHub in our repository.

We can now proceed to execute our benchmark tests and examine the results on the console:

| Method | Mean | Error | StdDev | Median | Allocated |
|----------------------- |------------:|---------:|---------:|------------:|-----------:|
| UseBinaryReader | 393.3 us | 6.89 us | 12.77 us | 386.7 us | 746.96 KB |
| UseBufferedStream | 462.4 us | 7.24 us | 5.65 us | 461.6 us | 2668.33 KB |
| UseMemoryStream | 522.8 us | 19.70 us | 58.07 us | 518.1 us | 2668.27 KB |
| UseStreamReader | 1,430.9 us | 22.01 us | 20.59 us | 1,428.9 us | 3756.39 KB |
| UseStreamDotReadMethod | 11,117.6 us | 54.63 us | 42.65 us | 11,117.2 us | 3920.87 KB |
| Method                 | Mean        | Error    | StdDev   | Median      | Allocated  |
|----------------------- |------------:|---------:|---------:|------------:|-----------:|
| UseBinaryReader        | 393.3 us    | 6.89 us  | 12.77 us | 386.7 us    | 746.96 KB  |
| UseBufferedStream      | 462.4 us    | 7.24 us  | 5.65 us  | 461.6 us    | 2668.33 KB |
| UseMemoryStream        | 522.8 us    | 19.70 us | 58.07 us | 518.1 us    | 2668.27 KB |
| UseStreamReader        | 1,430.9 us  | 22.01 us | 20.59 us | 1,428.9 us  | 3756.39 KB |
| UseStreamDotReadMethod | 11,117.6 us | 54.63 us | 42.65 us | 11,117.2 us | 3920.87 KB |

Based on the benchmark test results, we can see that the UseBinaryReader() is the fastest method to convert a stream to a byte[] array in C#. This method uses the least amount of time and memory among all the methods.

However, the UseBufferedStream() method comes in second place, while the UseMemoryStream() method comes in third place. These methods show similar completion time and memory usage.

Furthermore, the UseStreamReader() method is the fourth-fastest method. This approach has the second-highest memory allocation.

Finally, the slowest method for this benchmark test is the UseStreamDotReadMethod() method. It exhibits the slowest completion time and allocates more memory than the other methods.

Overall, we can see that the UseBinaryReader() method is the most optimal choice to convert a stream to a byte[] array in C#, given its low time and memory requirements.

Conclusion

In this article, we discussed five methods that we could use to convert a stream to a byte array in C#. Additionally, we performed benchmark tests to assess the speed and memory usage of all the methods.

Code Maze Book Collection

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API program and learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK