25 KiB
API Quick Reference
Quick reference for commonly used SharpCompress APIs.
Factory Methods
Opening Archives
// Auto-detect format
using (var reader = ReaderFactory.OpenReader(stream))
{
// Works with Zip, Tar, GZip, Rar, 7Zip, etc.
}
// Specific format - Archive API
using (var archive = ZipArchive.OpenArchive("file.zip"))
using (var archive = TarArchive.OpenArchive("file.tar"))
using (var archive = RarArchive.OpenArchive("file.rar"))
using (var archive = SevenZipArchive.OpenArchive("file.7z"))
using (var archive = GZipArchive.OpenArchive("file.gz"))
// With fluent options (preferred)
var options = ReaderOptions.ForEncryptedArchive("password")
.WithArchiveEncoding(new ArchiveEncoding { Default = Encoding.GetEncoding(932) });
using (var archive = ZipArchive.OpenArchive("encrypted.zip", options))
// Alternative: object initializer
var options2 = new ReaderOptions
{
Password = "password",
LeaveStreamOpen = true,
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
// Auto-detect and open with the Archive API
using (var archive = ArchiveFactory.OpenArchive("archive.zip"))
{
foreach (var entry in archive.Entries)
{
Console.WriteLine(entry.Key);
}
}
// Detect before opening
if (ArchiveFormat.IsArchive("archive.zip", out var archiveType))
{
Console.WriteLine($"Detected {archiveType}");
}
// Detect capabilities before choosing Archive API vs Reader API
var info = ArchiveFormat.GetInfo("archive.arc");
if (info is not null)
{
Console.WriteLine($"Type: {info.Type}");
Console.WriteLine($"Archive-wide compression: {info.CompressionType}");
Console.WriteLine($"Supports random access: {info.SupportsRandomAccess}");
}
var asyncInfo = await ArchiveFormat.GetInfoAsync(
"archive.zip",
cancellationToken
);
// Multi-volume archives
var parts = ArchiveFactory.GetFileParts("archive.part1.rar")
.Select(path => new FileInfo(path))
.ToArray();
using (var archive = ArchiveFactory.OpenArchive(parts))
{
archive.WriteToDirectory(@"C:\output");
}
ArchiveFormatInfo.CompressionType is the archive-wide or wrapper compression type. It is null for container formats such as Zip, Rar, 7Zip, Ace, Arc, and Arj because compression is stored per entry or internally; inspect IEntry.CompressionType after opening those archives. Raw tar reports CompressionType.None, and compressed tar wrappers report their wrapper compression, such as CompressionType.GZip for .tar.gz or CompressionType.Lzw for .tar.Z.
ArchiveFormatInfo.SupportsRandomAccess is true when the detected format supports IArchive random access. It is false for reader-only formats such as Ace, Arc, Arj, and standalone LZW, where ReaderFactory.OpenReader should be used instead. Compressed tar wrappers such as .tar.gz and .tar.xz are also reader-only; ArchiveFormat.GetInfo reports them as ArchiveType.Tar with SupportsRandomAccess = false, and ArchiveFactory.OpenArchive does not open them as the outer compression wrapper. Use ReaderFactory.OpenReader or TarReader.OpenReader for those files.
Breaking change: archive detection APIs live on ArchiveFormat. ArchiveFactory is only responsible for opening and creating archive API objects, and ArchiveInformation has been replaced by ArchiveFormatInfo.
Creating Archives
// Writer Factory
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Zip, CompressionType.Deflate))
{
// Write entries
}
// Specific writer
using (var archive = ZipArchive.CreateArchive())
using (var archive = TarArchive.CreateArchive())
using (var archive = GZipArchive.CreateArchive())
// With fluent options (preferred)
var options = WriterOptions.ForZip()
.WithCompressionLevel(9)
.WithLeaveStreamOpen(false)
.WithBufferSize(131072);
using (var archive = ZipArchive.CreateArchive())
{
archive.SaveTo("output.zip", options);
}
// Alternative: constructor with object initializer
var options2 = new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9,
LeaveStreamOpen = false,
BufferSize = 131072
};
WriterOptions.BufferSize controls stream copy buffers used while writing archive entries. If it is not set, SharpCompress falls back to Constants.BufferSize.
Archive API Methods
Reading/Extracting
using (var archive = ZipArchive.OpenArchive("file.zip"))
{
// Get all entries
IEnumerable<IArchiveEntry> entries = archive.Entries;
// Find specific entry
var entry = archive.Entries.FirstOrDefault(e => e.Key == "file.txt");
// Extract all
archive.WriteToDirectory(@"C:\output");
// Extract single entry
var firstEntry = archive.Entries.First();
firstEntry.WriteToFile(@"C:\output\file.txt");
// Extract single entry to a stream with extraction options
using (var outputStream = File.Create(@"C:\output\file.txt"))
{
firstEntry.WriteTo(
outputStream,
new ExtractionOptions { CheckCrc = false }
);
}
// Get entry stream
using (var stream = entry.OpenEntryStream())
{
stream.CopyTo(outputStream);
}
}
// Async extraction (requires IAsyncArchive)
await using (var asyncArchive = await ZipArchive.OpenAsyncArchive("file.zip"))
{
// Extract all entries asynchronously
await asyncArchive.WriteToDirectoryAsync(
@"C:\output",
cancellationToken: cancellationToken
);
}
// Open a specific entry stream asynchronously
await using (var asyncArchive = await ZipArchive.OpenAsyncArchive("file.zip"))
{
await foreach (var entry in asyncArchive.EntriesAsync)
{
await using (var outputStream = File.Create(@"C:\output\" + entry.Key))
{
await entry.WriteToAsync(
outputStream,
new ExtractionOptions { CheckCrc = false },
cancellationToken: cancellationToken
);
}
using (var stream = await entry.OpenEntryStreamAsync(cancellationToken))
{
// ...
}
}
}
Entry Properties
foreach (var entry in archive.Entries)
{
string name = entry.Key; // Entry name/path
long size = entry.Size; // Uncompressed size
long compressedSize = entry.CompressedSize;
bool isDir = entry.IsDirectory;
DateTime? modTime = entry.LastModifiedTime;
CompressionType compression = entry.CompressionType;
}
Creating Archives
using (var archive = ZipArchive.CreateArchive())
{
// Add file
archive.AddEntry("file.txt", @"C:\source\file.txt");
// Add multiple files
archive.AddAllFromDirectory(@"C:\source");
archive.AddAllFromDirectory(@"C:\source", "*.txt"); // Pattern
// Save to file
archive.SaveTo("output.zip", CompressionType.Deflate);
// Save to stream
archive.SaveTo(outputStream, new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9,
LeaveStreamOpen = true
});
}
Reader API Methods
Forward-Only Reading
using (var stream = File.OpenRead("file.zip"))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
IArchiveEntry entry = reader.Entry;
if (!entry.IsDirectory)
{
// Extract entry
reader.WriteEntryToDirectory(@"C:\output");
reader.WriteEntryToFile(@"C:\output\file.txt");
// Or get stream
using (var entryStream = reader.OpenEntryStream())
{
entryStream.CopyTo(outputStream);
}
}
}
}
// Async variants (use OpenAsyncReader to get IAsyncReader)
using (var stream = File.OpenRead("file.zip"))
await using (var reader = await ReaderFactory.OpenAsyncReader(stream))
{
while (await reader.MoveToNextEntryAsync())
{
await reader.WriteEntryToFileAsync(
@"C:\output\" + reader.Entry.Key,
cancellationToken: cancellationToken
);
}
// Async extraction of all entries
await reader.WriteAllToDirectoryAsync(
@"C:\output",
cancellationToken: cancellationToken
);
}
Writer API Methods
Creating Archives (Streaming)
using (var stream = File.Create("output.zip"))
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Zip, CompressionType.Deflate))
{
// Write single file
using (var fileStream = File.OpenRead("source.txt"))
{
writer.Write("entry.txt", fileStream, DateTime.Now);
}
// Write directory
writer.WriteAll("C:\\source", "*", SearchOption.AllDirectories);
writer.WriteAll("C:\\source", "*.txt", SearchOption.TopDirectoryOnly);
}
// Async variants: use OpenAsyncWriter to get IAsyncWriter
await using var stream = File.Create("output.zip");
await using var writer = await WriterFactory.OpenAsyncWriter(stream, ArchiveType.Zip, new WriterOptions(CompressionType.Deflate), cancellationToken);
using (var fileStream = File.OpenRead("source.txt"))
{
await writer.WriteAsync("entry.txt", fileStream, DateTime.Now, cancellationToken);
}
await writer.WriteAllAsync("C:\\source", "*", SearchOption.AllDirectories, cancellationToken);
Common Options
ReaderOptions
Use preset properties and fluent helpers for common configurations:
// External stream with password and custom encoding
var options = ReaderOptions.ForExternalStream
.WithPassword("password")
.WithArchiveEncoding(new ArchiveEncoding { Default = Encoding.GetEncoding(932) });
using (var archive = ZipArchive.OpenArchive("file.zip", options))
{
// ...
}
// Open-time presets
var external = ReaderOptions.ForExternalStream;
var owned = ReaderOptions.ForFilePath;
var encrypted = ReaderOptions.ForEncryptedArchive("password");
var encoded = ReaderOptions.ForEncoding(new ArchiveEncoding { Default = Encoding.UTF8 });
var sfx = ReaderOptions.ForSelfExtractingArchive("password");
// Faster detection when the container is known
var hinted = ReaderOptions.ForExternalStream.WithExtensionHint("tar.gz");
// Increase for non-seekable streams with large detection probes, such as SFX RAR
var buffered = ReaderOptions.ForExternalStream.WithRewindableBufferSize(1_048_576);
// Extraction presets
var safeOptions = ExtractionOptions.SafeExtract; // No overwrite
var flatOptions = ExtractionOptions.FlatExtract; // No directory structure
var metadataOptions = ExtractionOptions.PreserveMetadata; // Keep timestamps and attributes
// Tune extraction copy buffering
var extractionOptions = new ExtractionOptions
{
BufferSize = 131072,
CheckCrc = true, // Default: validate entry checksums when archive metadata provides one
};
// Factory defaults:
// - file path / FileInfo overloads use LeaveStreamOpen = false
// - stream overloads use LeaveStreamOpen = true
Alternative: traditional object initializer:
var options = new ReaderOptions
{
Password = "password",
LeaveStreamOpen = true,
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) },
ExtensionHint = "zip",
LookForHeader = true,
DisableCheckIncomplete = false,
BufferSize = 81920,
RewindableBufferSize = 1_048_576,
};
var extractionOptions = new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true,
BufferSize = 131072,
};
WriterOptions
Factory methods provide a clean, discoverable way to create writer options:
// Factory methods for common archive types
var zipOptions = WriterOptions.ForZip() // ZIP with Deflate
.WithCompressionLevel(9) // 0-9 for Deflate
.WithLeaveStreamOpen(false); // Close stream when done
var tarOptions = WriterOptions.ForTar(CompressionType.GZip) // TAR with GZip
.WithLeaveStreamOpen(false);
var gzipOptions = WriterOptions.ForGZip() // GZip file
.WithCompressionLevel(6);
archive.SaveTo("output.zip", zipOptions);
Use typed writer options when a format exposes extra settings:
// ZIP archive-level options
var zipWriterOptions = new ZipWriterOptions(CompressionType.Deflate)
{
ArchiveComment = "Created by SharpCompress",
UseZip64 = true,
CompressionLevel = 9,
};
// ZIP per-entry options
using (var writer = new ZipWriter(outputStream, zipWriterOptions))
using (var source = File.OpenRead("source.txt"))
{
writer.Write("entry.txt", source, new ZipWriterEntryOptions
{
CompressionType = CompressionType.ZStandard,
CompressionLevel = 3,
EntryComment = "per-entry comment",
ModificationDateTime = DateTime.UtcNow,
EnableZip64 = true,
});
}
// TAR-specific options
var tarOptions = new TarWriterOptions(CompressionType.GZip, finalizeArchiveOnClose: true)
{
HeaderFormat = TarHeaderWriteFormat.GNU_TAR_LONG_LINK,
};
// GZip-specific options
var gzipOptions = new GZipWriterOptions(compressionLevel: 9);
// 7z writing requires a seekable output stream and writes non-solid archives
var sevenZipOptions = new SevenZipWriterOptions(CompressionType.LZMA2)
{
CompressHeader = true,
LzmaProperties = new LzmaEncoderProperties(),
};
Alternative: traditional constructor with object initializer:
var options = new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9,
LeaveStreamOpen = true,
};
archive.SaveTo("output.zip", options);
Extraction behavior
var options = new ExtractionOptions
{
ExtractFullPath = true, // Recreate directory structure
Overwrite = true, // Overwrite existing files
PreserveFileTime = true, // Keep original timestamps
CheckCrc = true // Validate payload checksums when available
};
using (var archive = ZipArchive.OpenArchive("file.zip"))
{
archive.WriteToDirectory(@"C:\output", options);
}
CheckCrc validates archive-level payload checksums when the format stores reliable metadata, such as ZIP CRC32 values. Formats without payload checksums skip this validation. Decompressor integrity checks that are required to decode a stream may still fail even when CheckCrc is disabled.
Options matrix
ReaderOptions: open-time behavior (password, encoding, stream ownership)
ExtractionOptions: extract-time behavior (overwrite, paths, timestamps, attributes, symlinks)
WriterOptions: write-time behavior (compression type/level, encoding, stream ownership)
ZipWriterEntryOptions: per-entry ZIP overrides (compression, level, timestamps, comments, zip64)
Compression Providers
ReaderOptions and WriterOptions expose a Providers registry that controls which ICompressionProvider implementations are used for each CompressionType. The registry defaults to CompressionProviderRegistry.Default, so you only need to set it if you want to swap in a custom provider (for example the SystemGZipCompressionProvider or SystemDeflateCompressionProvider). The selected registry is honored by Reader/Writer APIs, Archive APIs, and async entry-stream extraction paths.
var registry = CompressionProviderRegistry.Default
.With(new SystemGZipCompressionProvider())
.With(new SystemDeflateCompressionProvider());
var readerOptions = ReaderOptions.ForFilePath.WithProviders(registry);
var writerOptions = new WriterOptions(CompressionType.GZip)
{
CompressionLevel = 6,
}.WithProviders(registry);
using var reader = ReaderFactory.OpenReader(input, readerOptions);
using var writer = WriterFactory.OpenWriter(output, ArchiveType.GZip, writerOptions);
Registry API summary:
CompressionProviderRegistry.Default: built-in provider registry
CompressionProviderRegistry.Empty: empty registry, primarily useful for tests
With(provider): returns a new registry with that provider added or replaced
GetProvider(type): returns the registered ICompressionProvider, or null
CreateCompressStream(...): creates a compression stream or throws if unsupported
CreateDecompressStream(...): creates a decompression stream or throws if unsupported
CreateCompressStreamAsync(...): async stream creation counterpart
CreateDecompressStreamAsync(...): async stream creation counterpart
GetCompressingProvider(type): returns ICompressionProviderHooks when available
ICompressionProvider implementations declare their CompressionType, whether they support compression/decompression, and create sync/async streams. For simple providers, derive from CompressionProviderBase; it supplies default async implementations that delegate to the synchronous methods. For read-only codecs, derive from DecompressionOnlyProviderBase.
public sealed class CustomGZipProvider : CompressionProviderBase
{
public override CompressionType CompressionType => CompressionType.GZip;
public override bool SupportsCompression => true;
public override bool SupportsDecompression => true;
public override Stream CreateCompressStream(Stream destination, int compressionLevel) =>
new GZipStream(destination, CompressionMode.Compress, leaveOpen: false);
public override Stream CreateDecompressStream(Stream source) =>
new GZipStream(source, CompressionMode.Decompress, leaveOpen: false);
}
CompressionContext carries metadata that providers may need when creating streams, including InputSize, OutputSize, Properties, CanSeek, FormatOptions, and ReaderOptions. Use CompressionContext.FromStream(stream) to populate stream-derived values, WithReaderOptions(...) to attach reader metadata, and ResolveArchiveEncoding() to get the archive header encoding from the context.
When a format needs additional initialization/finalization data (LZMA, PPMd, etc.) the registry exposes GetCompressingProvider which returns the ICompressionProviderHooks contract; the rest of the API continues to flow through Providers, including pre/properties/post compression hook data.
Compression Types
Available Compressions
// For creating archives
CompressionType.None // No compression (store)
CompressionType.GZip // GZip wrapper/combined tar compression
CompressionType.Deflate // DEFLATE (default for ZIP/GZip)
CompressionType.Deflate64 // Deflate64
CompressionType.BZip2 // BZip2
CompressionType.LZMA // LZMA (for 7Zip, LZip, XZ)
CompressionType.LZMA2 // LZMA2 (for 7Zip/XZ)
CompressionType.BCJ // 7Zip branch converter filter
CompressionType.BCJ2 // 7Zip branch converter filter
CompressionType.LZip // LZip wrapper/combined tar compression
CompressionType.Xz // XZ wrapper/combined tar compression
CompressionType.PPMd // PPMd (for ZIP)
CompressionType.Rar // RAR compression (read-only)
CompressionType.Lzw // LZW, including .Z/tar.Z reading
CompressionType.Shrink // ZIP shrink (read-only)
CompressionType.Reduce1 // ZIP reduce methods (read-only)
CompressionType.Reduce2
CompressionType.Reduce3
CompressionType.Reduce4
CompressionType.Explode // ZIP implode/explode (read-only)
CompressionType.Squeezed // ARC/ARJ legacy compression (read-only)
CompressionType.Packed // ARC legacy compression (read-only)
CompressionType.Crunched // ARC legacy compression (read-only)
CompressionType.Squashed // Legacy compression (read-only)
CompressionType.Crushed // Legacy compression (read-only)
CompressionType.Distilled // Legacy compression (read-only)
CompressionType.ZStandard // ZStandard
CompressionType.ArjLZ77 // ARJ compression (read-only)
CompressionType.AceLZ77 // ACE compression (read-only)
CompressionType.Unknown
// For Tar archives with compression
// Use WriterFactory to create compressed tar archives
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Tar, CompressionType.GZip)) // Tar.GZip
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Tar, CompressionType.BZip2)) // Tar.BZip2
Archive Types
ArchiveType.Zip
ArchiveType.Tar
ArchiveType.GZip
ArchiveType.BZip2
ArchiveType.Rar
ArchiveType.SevenZip
ArchiveType.Arc
ArchiveType.Arj
ArchiveType.Ace
ArchiveType.Lzw
Patterns & Examples
Extract with Error Handling
try
{
using (var archive = ZipArchive.OpenArchive("archive.zip",
ReaderOptions.ForEncryptedArchive("password")))
{
archive.WriteToDirectory(@"C:\output");
}
}
catch (PasswordRequiredException)
{
Console.WriteLine("Password required");
}
catch (InvalidArchiveException)
{
Console.WriteLine("Archive is invalid");
}
catch (SharpCompressException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Extract with Progress
var progress = new Progress<ProgressReport>(report =>
{
Console.WriteLine($"Extracting {report.EntryPath}: {report.PercentComplete}%");
});
var options = ReaderOptions.ForFilePath.WithProgress(progress);
using (var archive = ZipArchive.OpenArchive("archive.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
Async Extract with Cancellation
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(5));
try
{
await using (var archive = await ZipArchive.OpenAsyncArchive("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
cancellationToken: cts.Token
);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Extraction cancelled");
}
Create with Custom Compression
using (var archive = ZipArchive.CreateArchive())
{
archive.AddAllFromDirectory(@"D:\source");
// Fastest
archive.SaveTo("fast.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 1
});
// Balanced (default)
archive.SaveTo("normal.zip", CompressionType.Deflate);
// Best compression
archive.SaveTo("best.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9
});
}
Stream Processing (No File I/O)
using (var outputStream = new MemoryStream())
using (var archive = ZipArchive.CreateArchive())
{
// Add content from memory
using (var contentStream = new MemoryStream(Encoding.UTF8.GetBytes("Hello")))
{
archive.AddEntry("file.txt", contentStream);
}
// Save to memory
archive.SaveTo(outputStream, CompressionType.Deflate);
// Get bytes
byte[] archiveBytes = outputStream.ToArray();
}
Buffered Forward-Only Streams
SharpCompressStream can wrap streams with buffering for forward-only scenarios:
// Wrap a non-seekable stream with buffering
using (var bufferedStream = new SharpCompressStream(rawStream))
{
// Provides ring buffer functionality for reading ahead
// and seeking within buffered data
using (var reader = ReaderFactory.OpenReader(bufferedStream))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(@"C:\output");
}
}
}
Useful for:
- Non-seekable streams (network streams, pipes)
- Forward-only reading with limited look-ahead
- Buffering unbuffered streams for better performance
Extract Specific Files
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
var filesToExtract = new[] { "file1.txt", "file2.txt" };
foreach (var entry in archive.Entries.Where(e => filesToExtract.Contains(e.Key)))
{
entry.WriteToFile(@"C:\output\" + entry.Key);
}
}
List Archive Contents
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
foreach (var entry in archive.Entries)
{
if (entry.IsDirectory)
Console.WriteLine($"[DIR] {entry.Key}");
else
Console.WriteLine($"[FILE] {entry.Key} ({entry.Size} bytes)");
}
}
Common Mistakes
✗ Wrong - Stream not disposed
var stream = File.OpenRead("archive.zip");
var archive = ZipArchive.OpenArchive(stream);
archive.WriteToDirectory(@"C:\output");
// stream not disposed - leaked resource
✓ Correct - Using blocks
using (var stream = File.OpenRead("archive.zip"))
using (var archive = ZipArchive.OpenArchive(stream))
{
archive.WriteToDirectory(@"C:\output");
}
// Both properly disposed
✗ Wrong - Mixing API styles
// Loading entire archive then iterating
using (var archive = ZipArchive.OpenArchive("large.zip"))
{
var entries = archive.Entries.ToList(); // Loads all in memory
foreach (var e in entries)
{
e.WriteToFile(...); // Then extracts each
}
}
✓ Correct - Use Reader for large files
// Streaming iteration
using (var stream = File.OpenRead("large.zip"))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(@"C:\output");
}
}
Related Documentation
- USAGE.md - Complete code examples
- FORMATS.md - Supported formats
- PERFORMANCE.md - API selection guide