How to stream to a file in C#?

A thumbnail showing C# Stream code.

Stream to a file in C#

To stream from memory to a file in C#:

  1. Create and populate the MemoryStream.
  2. Use the File.Open method to create a FileStream on the specified path with read/write access.
  3. Reset the position of the MemoryStream before copying to make sure it save the entire content.
  4. Use CopyTo method to read the bytes from the MemoryStream and write them to the FileStream.
  5. Make sure you're disposing the streams by wrapping your code in the using statements.

Here's the full code to stream from memory to a file:

csharp
using System.IO;

string fileToWriteTo = "test.txt";
byte[] test = Encoding.ASCII.GetBytes("C# Stream to File Example");

using(MemoryStream memoryStream = new MemoryStream(test))
{
    using Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create);

    memoryStream.Position = 0;
    await memoryStream.CopyToAsync(streamToWriteTo);
}

How to stream HTTP response to a file?

To stream the HTTP response to file in C#:

  1. Get the instance of HTTP client
  2. Use the GetStreamAsync method of the HTTP client to stream the HTTP response.
  3. Use the CopyToAsync method to write to the output file.

Here's the full code to stream HTTP response to a file:

csharp
using System.IO;
using System.Net.Http;

using (HttpClient client = new HttpClient()) // Use dependency injection to get the HttpClient in your application!
{
    const string url = "https://raw.githubusercontent.com/hashicorp/next-mdx-remote/main/README.md";
    using Stream streamToReadFrom = await client.GetStreamAsync(url);
        
    string fileToWriteTo = "test.txt";
    using Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create);
    await streamToReadFrom.CopyToAsync(streamToWriteTo);    
} 

GetAsync vs GetStreamAsync

The main difference between GetAsync and GetStreamAsync is that GetAsync loads the entire HTTP response to memory, while GetStreamAsync streams the response in smaller chunks.

Under the hood, GetStreamAsync reads the HTTP headers to get the content length. That allows it to chunk the rest of the response body.

What is a Stream in C#?

A stream is a sequence of bytes that we can read from or write to.

The base of all streams in C# is the abstract Stream class.

There are many types of streams that inherit from the Stream base class, such as:

  • FileStream,
  • MemoryStream,
  • BufferedStream,
  • GZipStream,
  • SslStream

The Stream class defines methods and properties for fundamental operations:

  • reading
  • writing
  • seeking
  • managing (configure, close, flush)

Position vs Seek

The main difference between the Position property and Seek method is that Position is relative to the beginning of the stream. On the other hand, the Seek method is relative to the current position or the end of the stream.

Read-only vs write-only

The main difference between read-only and write-only streams in C# is that if CanWrite returns false, the stream is read-only. But if CanRead returns false, the stream is write-only.

Why do we need to dispose a file stream?

When working with files, we need to make sure we're disposing resources because they can cause a memory leak in our application.

.NET takes care of a lot of memory management for us, but not all of it.

Unmanaged resources are all the resources outside of .NET. In the case of FileStream, it's the file system of the underlying Operating System.

When you open a file to read or write to it, you are using resources outside of .NET. These are called unmanaged resources and must be disposed of when you are done working with them.

Published on