PROWAREtech
.NET: Using Brotli to Compress and Decompress Data
How to use the BrotliStream class to compress and decompress bytes, files or streams of data in C#.
.NET makes compressing and decompressing data with this popular Brotli compression algorithm incredibly easy. Compress and decompress byte arrays for simplicity or work with files and streams for purposes of efficiency.
See related articles: Compress Data with GZipStream, Compress and Upload Files with Blazor WASM, Compress HTTPS Blazor WASM WebAPI Output and Compress HTTPS .NET Core WebAPI Output
This library will compress streams from the position they are at, so put the input stream at position 0 if wanting to compress the whole stream.
// BrotliCompressor.cs
using System;
using System.IO;
using System.IO.Compression;
using System.Threading;
using System.Threading.Tasks;
namespace Utilities
{
public class Brotli
{
private static CompressionLevel GetCompressionLevel()
{
if (Enum.IsDefined(typeof(CompressionLevel), 3)) // NOTE: CompressionLevel.SmallestSize == 3 is not supported in .NET Core 3.1
{
return (CompressionLevel)3;
}
return CompressionLevel.Optimal;
}
public static byte[] CompressBytes(byte[] bytes) => CompressBytesAsync(bytes).GetAwaiter().GetResult();
public static async Task<byte[]> CompressBytesAsync(byte[] bytes, CancellationToken cancel = default(CancellationToken))
{
using (var outputStream = new MemoryStream())
{
using (var compressionStream = new BrotliStream(outputStream, GetCompressionLevel()))
{
await compressionStream.WriteAsync(bytes, 0, bytes.Length, cancel);
}
return outputStream.ToArray();
}
}
public static void CompressFile(string originalFileName, string compressedFileName) => CompressFileAsync(originalFileName, compressedFileName).GetAwaiter().GetResult();
public static async Task CompressFileAsync(string originalFileName, string compressedFileName, CancellationToken cancel = default(CancellationToken))
{
using (FileStream originalStream = File.Open(originalFileName, FileMode.Open))
{
using (FileStream compressedStream = File.Create(compressedFileName))
{
await CompressStreamAsync(originalStream, compressedStream, cancel);
}
}
}
public static void CompressStream(Stream originalStream, Stream compressedStream) => CompressStreamAsync(originalStream, compressedStream).GetAwaiter().GetResult();
public static async Task CompressStreamAsync(Stream originalStream, Stream compressedStream, CancellationToken cancel = default(CancellationToken))
{
using (var compressor = new BrotliStream(compressedStream, GetCompressionLevel()))
{
await originalStream.CopyToAsync(compressor, cancel);
}
}
public static byte[] DecompressBytes(byte[] bytes) => DecompressBytesAsync(bytes).GetAwaiter().GetResult();
public static async Task<byte[]> DecompressBytesAsync(byte[] bytes, CancellationToken cancel = default(CancellationToken))
{
using (var inputStream = new MemoryStream(bytes))
{
using (var outputStream = new MemoryStream())
{
using (var compressionStream = new BrotliStream(inputStream, CompressionMode.Decompress))
{
await compressionStream.CopyToAsync(outputStream, cancel);
}
return outputStream.ToArray();
}
}
}
public static void DecompressFile(string compressedFileName, string outputFileName) => DecompressFileAsync(compressedFileName, outputFileName).GetAwaiter().GetResult();
public static async Task DecompressFileAsync(string compressedFileName, string outputFileName, CancellationToken cancel = default(CancellationToken))
{
using (FileStream compressedFileStream = File.Open(compressedFileName, FileMode.Open))
{
using (FileStream outputFileStream = File.Create(outputFileName))
{
await DecompressStreamAsync(compressedFileStream, outputFileStream, cancel);
}
}
}
public static void DecompressStream(Stream compressedStream, Stream outputStream) => DecompressStreamAsync(compressedStream, outputStream).GetAwaiter().GetResult();
public static async Task DecompressStreamAsync(Stream compressedStream, Stream outputStream, CancellationToken cancel = default(CancellationToken))
{
using (var decompressor = new BrotliStream(compressedStream, CompressionMode.Decompress))
{
await decompressor.CopyToAsync(outputStream, cancel);
}
}
}
}
It is easy to use this code on files to compress and decompress them.
var bytes = System.IO.File.ReadAllBytes("TEMP.txt"); // MAKE SURE TEMP.txt EXISTS!!!
Console.WriteLine("INPUT FILE IS " + bytes.Length + " bytes");
bytes = Utilities.Brotli.CompressBytes(bytes);
Console.WriteLine("COMPRESSED FILE IS " + bytes.Length + " bytes");
System.IO.File.WriteAllBytes("TEMP.br", bytes);
bytes = Utilities.Brotli.DecompressBytes(bytes);
Console.WriteLine("DECOMPRESSED FILE IS " + bytes.Length + " bytes");
System.IO.File.WriteAllBytes("TEMP2.txt", bytes);
Comment