skip to content
Khalid Abuhakmeh logo Khalid Abuhakmeh

C# Zip File: Create and Extract Zip Archives

How to create a C# zip file with ZipFile and ZipArchive: compress directories, add files one by one, work with streams, and extract archives.

7 min read Updated

To create a C# zip file, use ZipFile.CreateFromDirectory for a whole folder, or open a ZipArchive and call CreateEntryFromFile/CreateEntry when you need to pick individual files or write from a stream. Both live in System.IO.Compression and ship with .NET, no extra packages needed.

Updated November 2026 for modern .NET (.NET 8/9). All examples use the built-in System.IO.Compression types, no NuGet packages required.

Pick the approach that matches your scenario:

You want to… Use Lives on
Zip an entire folder in one call ZipFile.CreateFromDirectory ZipFile
Add specific files one at a time ZipFile.Open + CreateEntryFromFile ZipArchive
Write a zip entry from a Stream (in-memory) ZipFile.Open + CreateEntry ZipArchive
Extract a zip to a folder ZipFile.ExtractToDirectory ZipFile
Read entries without extracting to disk ZipFile.OpenRead ZipArchive

ZipFile is the high-level static helper for whole-directory operations. ZipArchive is the lower-level type you reach for when you need entry-by-entry control. The rest of this post walks through each.

Zip files are the most ubiquitous compression format in computing history, with it first being invented in 1986 by Phillip Katz. Since then, the Zip file has found its way into every operating system as the de facto compression method. It’s only right that .NET developers become familiar with the format and have the necessary tools to work with these files programmatically.

In this post, we’ll cover the ZipFile utility class, how to compress files and directories, and how to decompress zip files. By the end, you’ll know how to create a Zip file in C# with .NET Core (and modern .NET), whether you’re zipping an entire directory or creating a zip file from multiple files picked one at a time.

Using ZipFile in System.IO.Compression

Microsoft introduced the ZipFile class in .NET Framework 4.5, and it’s available on all modern .NET versions (.NET Core 1.0+ through .NET 9). On modern SDK-style projects, the System.IO.Compression types are part of the shared framework, so you don’t need to add any NuGet package or assembly reference to use them. Just add the namespace:

using System.IO.Compression;

(On legacy .NET Framework projects, you still need a reference to the System.IO.Compression.FileSystem assembly for the file-system-dependent methods like CreateFromDirectory.)

How do I create a zip file using System.IO.Compression.ZipFile?

To create a zip file in C# using System.IO.Compression.ZipFile, call ZipFile.CreateFromDirectory with your source folder path and target archive path. This static method compresses all files and nested subdirectories into a standard .zip archive on disk using CompressionLevel.Optimal by default, requiring no third-party NuGet packages on modern .NET (.NET Core 1.0+ through .NET 9).

using System.IO.Compression;
// Zip an entire directory in one call
ZipFile.CreateFromDirectory(
sourceDirectoryName: @"./source_directory",
destinationArchiveFileName: @"./archive.zip"
);

For full control over compression speed, base folder inclusion, or filename encoding, use the optional parameters:

using System.IO.Compression;
using System.Text;
ZipFile.CreateFromDirectory(
sourceDirectoryName: @"./source_directory",
destinationArchiveFileName: @"./archive.zip",
compressionLevel: CompressionLevel.SmallestSize,
includeBaseDirectory: false,
entryNameEncoding: Encoding.UTF8
);

Adding Individual Files to a Zip File (ZipArchive)

For developers who want more control over compressing a directory, they can loop through a directory’s contents and add files individually, which is how to create a zip file from multiple files in C#. This technique is useful when you only want to add specific files, such as images or video files. It’s important to call Dispose on the ZipArchive to ensure the creation of a valid zip file. In the example below, we are declaring a scoped variable with the using keyword.

using System;
using System.IO;
using System.IO.Compression;
var images = Directory.GetFiles(@"./", "*.png");
if (File.Exists("archive.zip"))
File.Delete("archive.zip");
using var archive =
ZipFile
.Open(@"archive.zip", ZipArchiveMode.Create);
foreach (var image in images)
{
var entry =
archive.CreateEntryFromFile(
image,
Path.GetFileName(image),
CompressionLevel.Optimal
);
Console.WriteLine($"{entry.FullName} was compressed.");
}

If we need to archive an entity that only exists in memory, we can use Stream objects. We can use the CopyToAsync method found on most streams to copy directly into our ZipEntry instance.

using System;
using System.IO;
using System.IO.Compression;
var images = Directory.GetFiles(@"./", "*.png");
if (File.Exists("archive.zip"))
File.Delete("archive.zip");
using var archive =
ZipFile
.Open(@"archive.zip", ZipArchiveMode.Create);
// we're getting a file stream
// here but it could be any stream
var file = File.OpenRead(images[0]);
var entry =
archive.CreateEntry(
"test.png",
CompressionLevel.Optimal
);
await file.CopyToAsync(entry.Open());
Console.WriteLine($"{entry.FullName} was compressed.");

These are a few ways to create zip files in a C# application, but how do you retrieve entries from a zip file?

Decompressing a Zip File Examples

The most straightforward approach is to use the ExtractToDirectory method found on the ZipFile class. This method will write entries to a directory on disk, which can then we can then access using our file system.

using System;
using System.IO;
using System.IO.Compression;
ZipFile.ExtractToDirectory(
@"./archive.zip",
@"./destination_directory",
overwriteFiles: true
);

If we need to perform post-processing for zip file entries, we can use the OpenFile method on ZipFile to create a ZipArchive instance.

using System;
using System.IO;
using System.IO.Compression;
var archive = ZipFile.OpenRead(@"./archive.zip");
foreach (var entry in archive.Entries)
{
Console.WriteLine(entry.Name);
var stream = entry.Open();
// read stream
// push to the cloud?
// do whatever you like!
}

As we can see, the process of working with an existing zip file and its contents is straightforward, and the ability to work with Stream instances gives us the ability to push resources from zip files to any other storage mechanism.

Frequently Asked Questions

How do I extract a zip file to a directory in C#?

Call ZipFile.ExtractToDirectory(@"./archive.zip", @"./destination_directory"). This decompresses all entries from the archive into the target folder on disk, creating the directory hierarchy automatically if it does not already exist.

How do I overwrite existing files when extracting a zip in C#?

Pass overwriteFiles: true to ZipFile.ExtractToDirectory(@"./archive.zip", @"./destination_directory", overwriteFiles: true). In modern .NET (.NET Core 2.0+ and .NET 5+ through .NET 9), this flag tells the extractor to replace matching files rather than throwing an IOException.

What compression levels does ZipFile support in .NET?

The CompressionLevel enum in System.IO.Compression supports four settings:

  • CompressionLevel.Optimal: Balances file size and execution speed (the default setting).
  • CompressionLevel.Fastest: Finishes compression quickly at the cost of slightly larger archive size.
  • CompressionLevel.NoCompression: Packages files into the archive with zero compression for instant bundling.
  • CompressionLevel.SmallestSize: Available in .NET 6+, trades additional CPU cycles and memory to achieve maximum compression ratio.

What is the difference between ZipFile and ZipArchive in C#?

ZipFile is a static helper class with convenience methods that operate on the file system in a single call, such as CreateFromDirectory, ExtractToDirectory, and OpenRead. ZipArchive represents the archive itself and gives you entry-by-entry control through CreateEntry, CreateEntryFromFile, and the Entries collection. Use ZipFile for whole-folder operations; use ZipArchive when you need to add, read, or update individual entries.

How do I create a zip file from multiple files in C#?

Open a ZipArchive in ZipArchiveMode.Create with ZipFile.Open, then call CreateEntryFromFile for each file you want to include. This lets you filter which files get added, for example, only *.png images, instead of zipping an entire directory.

Do I need a NuGet package to create a zip file in .NET?

No. On modern SDK-style projects (.NET Core and .NET 5+), the System.IO.Compression and System.IO.Compression.ZipFile types are part of the shared framework. Add using System.IO.Compression; and you’re ready to go, no package reference required.

How do I add a zip entry from a stream instead of a file?

Call CreateEntry on a ZipArchive to get a new ZipArchiveEntry, open it with entry.Open(), and copy your source stream into it with CopyToAsync. This is ideal for data that only exists in memory and never touches disk.

Conclusion

Zip files are an essential format for developers to understand. While not the most efficient compression format, it is ubiquitous and understood by all technology stacks. It allows us to pass logically grouped files in a single stream of data, which can be useful in many user scenarios. Luckily for .NET developers, the ZipFile utility class provides more than enough functionality for this compression approach, along with many ways to work with this file format.

If you found this post helpful, please share it with your friends and co-workers. As always, thanks for reading.

References

Comments

Related Posts