In this article, we’ll discuss how to convert a stream to a file in C#. We will demonstrate different ways to do that, discuss the advantages and disadvantages of each, and see when one way could be more suitable.
Let’s dive in.
What Is a Stream
A stream is an abstraction of a sequence of bytes. The Stream class in .NET is an abstract class that implements the methods enabling stream operations, such as reading and writing to streams and positioning in a stream, among others.
The source and the destination of the sequence of the bytes can be various. For example, it can be a file, different input or output device, network, or similar. .NET implements a few classes that derive from the Stream
class and deal with these different sources and destinations for a stream. That includes FileStream
, MemoryStream
, NetworkStream
, and other classes.
The Stream class and derived classes implement numerous methods for reading and writing from a stream, such as Read()
, ReadAsync()
, ReadByte()
, Write()
, WriteAsync()
, and WriteByte()
.
How to Convert a Stream to a File in C#
Let’s describe several ways to convert a stream to a file in C#. First, we need to prepare our stream and path for a file:
var sourceFile = Path.Combine([directory, "Files", "source.png"]); var destinationPath = Path.Combine([directory, "Files"]); using var fileStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read); using var memoryStream = new MemoryStream(); fileStream.CopyTo(memoryStream);
The source image is in the Files
subfolder. We will store the resulting file in the same folder. We load the source image to a FileStream
and copy this stream to a MemoryStream
. This MemoryStream
is the input parameter for all methods where we convert it to a file. The second parameter of this method is a path for the destination file.
Convert a Stream to a File Using CopyTo
The CopyTo()
method of the Stream
class copies from one stream to another:
public static void CopyToFile(MemoryStream stream, string path) { using var fileStream = File.Create(path); stream.Position = 0; stream.CopyTo(fileStream); }
We create a FileStream
using the File.Create()
method. The parameter of this method is the path where we want to save our file. After that, we position our source stream to 0 and then call the CopyTo()
method on the Stream class.
Convert a Stream to a File Using Write
The FileStream.Write()
method accepts a ReadOnlySpan<byte>
argument and writes it to a file:
public static void WriteToFileStream(MemoryStream stream, string path) { using var fileStream = File.Create(path); fileStream.Write(stream.ToArray()); }
First, we convert the input stream to a byte[]
. The ToArray()
method of the MemoryStream
class converts the stream content to an array entirely. In this case, we don’t have to position the input stream to 0 before writing to a file, as the ToArray()
method writes the entire stream content to an array, regardless of the position. The Write()
method then implicitly converts this array to a ReadOnlySpan<byte>
and writes all bytes to a destination fileStream
stream.
Convert a Stream to a File Using WriteByte
The FileStream
class has the WriteByte()
method which accepts one byte that it then writes to another stream:
public static void WriteByteToFileStream(MemoryStream stream, string path) { using var fileStream = File.Create(path); stream.Position = 0; while (stream.Position < stream.Length) { fileStream.WriteByte((byte)stream.ReadByte()); } }
After creating the destination fileStream
stream and positioning it at the first byte, we start a loop where we read one byte at a time with the ReadByte()
method. This method returns an int
value, so we must convert it to a byte
data type that we write to the destination stream.
Convert a Stream to a File Using WriteAllBytes
The File
class has a static WriteAllBytes()
method that accepts the path and an array of bytes to write to the file:
public static void WriteAllBytesFile(MemoryStream stream, string path) { File.WriteAllBytes(path, stream.ToArray()); }
We pass the destination path to the static method and convert the input stream to the byte array.
Benchmark of Converting Stream to File
In addition, we’ll benchmark each of these examples to see the best way to perform this conversion from a performance perspective:
| Method | Mean | Error | StdDev | Median | Allocated | |----------------------- |---------:|---------:|---------:|---------:|----------:| | CopyToBenchmark | 125.5 us | 2.46 us | 3.28 us | 125.1 us | 672 B | | WriteAllBytesBenchmark | 133.1 us | 2.61 us | 5.33 us | 133.4 us | 520 B | | WriteByteBenchmark | 135.9 us | 2.97 us | 7.92 us | 135.4 us | 680 B | | WriteBenchmark | 144.5 us | 10.55 us | 29.93 us | 129.4 us | 672 B |
As we can see, all methods perform approximately the same. However, the CopyTo()
method is a little bit faster. Moreover, if we run benchmark tests several times, other methods, except CopyTo()
, perform slightly differently and not necessarily in this order.
From a memory consumption perspective, the WriteAllBytes()
method is the least demanding.
Conclusion
Summing up, we have several options for converting a stream to a file in C#. However, all of these options are very similar, and using them may only be a matter of personal preference.
A slightly more performant method is the Stream.CopyTo() method, but the File.WriteAllBytes() method is the best when we look at memory consumption.