C#
File Streaming
Programming
Code Saving
File Manipulation

How do I save a stream to a file in C#?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Saving a stream to a file in C# is usually a matter of copying bytes from one Stream to another. The important parts are choosing the right API, disposing resources correctly, and remembering that some input streams must be rewound before you copy them.

The Simplest Approach: CopyTo

If you already have a Stream, the most direct solution is to open a FileStream and call CopyTo. This works for MemoryStream, NetworkStream, upload streams, and many other Stream implementations.

csharp
1using System;
2using System.IO;
3using System.Text;
4
5public static class Program
6{
7    public static void Main()
8    {
9        using var source = new MemoryStream(Encoding.UTF8.GetBytes("Hello from a stream."));
10        using var destination = File.Create("output.txt");
11
12        source.CopyTo(destination);
13    }
14}

File.Create returns a writable FileStream, and the using statements ensure both streams are disposed even if an exception occurs. For many cases, this is all you need.

A Reusable Helper Method

When the same pattern appears in several places, wrap it in a small helper method. That keeps file creation details out of the rest of the code.

csharp
1using System;
2using System.IO;
3
4public static class StreamSaver
5{
6    public static void SaveToFile(Stream input, string filePath)
7    {
8        if (input == null) throw new ArgumentNullException(nameof(input));
9        if (filePath == null) throw new ArgumentNullException(nameof(filePath));
10
11        using var output = new FileStream(
12            filePath,
13            FileMode.Create,
14            FileAccess.Write,
15            FileShare.None);
16
17        input.CopyTo(output);
18    }
19}

Usage is straightforward:

csharp
using var source = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
StreamSaver.SaveToFile(source, "data.bin");

This version overwrites the file if it already exists because it uses FileMode.Create. If you want to append instead, open the file with FileMode.Append, but remember that appending only makes sense for formats that support it cleanly.

Watch the Stream Position

One frequent source of confusion is stream position. If the stream has already been read from or written to, its current position may be at the end. In that case, CopyTo will copy zero bytes because there is nothing left to read from the current position onward.

csharp
1using System;
2using System.IO;
3using System.Text;
4
5public static class Program
6{
7    public static void Main()
8    {
9        using var source = new MemoryStream();
10
11        byte[] bytes = Encoding.UTF8.GetBytes("Example text");
12        source.Write(bytes, 0, bytes.Length);
13
14        source.Position = 0;
15
16        using var output = File.Create("example.txt");
17        source.CopyTo(output);
18    }
19}

Resetting Position to 0 is common for MemoryStream. Some streams are not seekable, so you cannot always rewind them. For example, a network stream may only move forward. In those cases, copy the stream at the moment you receive it or buffer it elsewhere first.

Async Copy for I/O-Bound Work

If the data source or destination is slow, the asynchronous API is often a better fit. This is especially useful in ASP.NET applications where blocking a thread on file or network I/O is wasteful.

csharp
1using System.IO;
2using System.Threading.Tasks;
3
4public static class StreamSaver
5{
6    public static async Task SaveToFileAsync(Stream input, string filePath)
7    {
8        await using var output = new FileStream(
9            filePath,
10            FileMode.Create,
11            FileAccess.Write,
12            FileShare.None,
13            bufferSize: 81920,
14            useAsync: true);
15
16        await input.CopyToAsync(output);
17    }
18}

In a web application, this might be used with an uploaded file stream:

csharp
await StreamSaver.SaveToFileAsync(upload.OpenReadStream(), "upload.bin");

The logic is still simple, but the async version scales better when many requests are performing I/O at once.

Binary Data Versus Text

A stream is just bytes. Saving the stream to disk does not care whether the content represents text, an image, or a compressed archive. The only thing that changes is how you created the source stream and what file name you choose.

If you start with a string rather than a stream, you usually do not need stream APIs at all. File.WriteAllText or File.WriteAllBytes can be simpler. Use stream copying when the input already exists as a Stream or when you want one code path that works for many stream sources.

Common Pitfalls

  • Forgetting to dispose the source or destination stream.
  • Copying from a stream whose position is already at the end.
  • Assuming every stream supports seeking and can be rewound.
  • Using synchronous file I/O in server code where CopyToAsync would be a better fit.
  • Reimplementing byte-copy loops manually when CopyTo already handles that correctly.

Summary

  • To save a stream to a file in C#, open a FileStream and call CopyTo or CopyToAsync.
  • Use using or await using so resources are released reliably.
  • Check the current stream position before copying.
  • Prefer async copying for web apps and other I/O-heavy workloads.
  • Use simpler file APIs only when your source data is not already a stream.

Course illustration
Course illustration

All Rights Reserved.