GitHub - kingsznhone/FastLZMA2Net: Fast LZMA2 Wrapper for .NET (original) (raw)

Fast LZMA2 Compression algorithm Wrapper for .NET

⚠️This library is not designed to generate valid 7z archives; it is solely responsible for compressing and decompressing individual byte streams.

Change Log

With respect to Fast LZMA2 repo

Requirements

.NET 8 / .NET 10

OS Architectures
Windows x64 · x86 · arm64
Linux (glibc) x64 · x86 · arm64 · arm
Linux (musl / Alpine) x64 · arm64

x86 may have potential malfunction.

Installation

PM> Install-Package FastLZMA2Net

API Overview

Class Description
FL2 Static helpers — one-shot compress / decompress, memory estimation
Compressor Reusable compression context
Decompressor Reusable decompression context
CompressStream Streaming compression (Stream subclass)
DecompressStream Streaming decompression (Stream subclass)

Usage

Simple compression

byte[] origin = File.ReadAllBytes(sourceFilePath); byte[] compressed = FL2.Compress(origin, level: 6); byte[] decompressed = FL2.Decompress(compressed);

ReadOnlySpan<byte> overloads are available to avoid a copy when data is already in a pooled or stack-allocated buffer:

ReadOnlySpan span = ...; byte[] compressed = FL2.Compress(span, level: 6);

Multi-threaded one-shot compression

byte[] compressed = FL2.CompressMT(origin, level: 6, nbThreads: 0); // 0 = all cores byte[] decompressed = FL2.DecompressMT(compressed, nbThreads: 0);

Context Compression

Reuse a Compressor / Decompressor to amortize context-allocation cost across many calls (e.g. batches of small files).

using Compressor compressor = new(nbThreads: 0) { CompressLevel = 10 }; byte[] c1 = compressor.Compress(data1); byte[] c2 = compressor.Compress(data2);

using Decompressor decompressor = new(); byte[] d1 = decompressor.Decompress(c1); byte[] d2 = decompressor.Decompress(c2);

Async compression

using Compressor compressor = new(nbThreads: 0) { CompressLevel = 6 }; byte[] compressed = await compressor.CompressAsync(origin, cancellationToken);

using Decompressor decompressor = new(); byte[] decompressed = await decompressor.DecompressAsync(compressed, cancellationToken);

File-to-file compression (no memory copy)

Uses memory-mapped I/O — no full read into managed memory.

using Compressor compressor = new(nbThreads: 0) { CompressLevel = 6 }; nuint compressedBytes = compressor.Compress(sourceFilePath, destFilePath);

Streaming Compression

CompressStream is a writable Stream and DecompressStream is a readable Stream. Pipe any stream in or out via Write / CopyTo / CopyToAsync — there is no size restriction. The compress stream is finalised automatically when Dispose() is called.

Compress

// in-memory using MemoryStream ms = new(); using (CompressStream cs = new(ms) { CompressLevel = 10 }) cs.Write(origin); byte[] compressed = ms.ToArray();

// file (works for any size) using FileStream sourceFile = File.OpenRead(sourceFilePath); using FileStream compressedFile = File.Create(compressedFilePath); using (CompressStream cs = new(compressedFile) { CompressLevel = 10 }) sourceFile.CopyTo(cs);

Compress (async)

await using FileStream sourceFile = File.OpenRead(sourceFilePath); await using FileStream compressedFile = File.Create(compressedFilePath); await using (CompressStream cs = new(compressedFile) { CompressLevel = 10 }) await sourceFile.CopyToAsync(cs);

Decompress

// in-memory using MemoryStream recoveryStream = new(); using (DecompressStream ds = new(new MemoryStream(compressed))) ds.CopyTo(recoveryStream); byte[] decompressed = recoveryStream.ToArray();

// file (works for any size) using FileStream compressedFile = File.OpenRead(compressedFilePath); using FileStream recoveryFile = File.Create(decompressedFilePath); using (DecompressStream ds = new(compressedFile)) ds.CopyTo(recoveryFile);

Fine-tune compression parameters

using Compressor compressor = new(nbThreads: 0) { CompressLevel = 10 }; compressor.SetParameter(FL2Parameter.FastLength, 48); compressor.SetParameter(FL2Parameter.SearchDepth, 60);

Estimate memory usage

// By compression level and thread count nuint size = FL2.EstimateCompressMemoryUsage(compressionLevel: 10, nbThreads: 8);

// Using an existing context's settings using Compressor compressor = new(nbThreads: 4) { CompressLevel = 10 }; nuint size = FL2.EstimateCompressMemoryUsage(compressor.CompressLevel, compressor.ThreadCount);

Find decompressed size

// From a byte array nuint size = FL2.FindDecompressedSize(compressedData);

// From a file path (uses memory-mapped I/O — no full read into memory) nuint size = FL2.FindDecompressedSize(compressedFilePath);

Bug report

Open an issue.

Contribution

PR is welcome.