Zippy

A Quick Compression Module


Compression can be quick and easy in PowerShell

Compression can be quick and easy with .NET.

Let's learn how.

Yesterday I just dusted off some old code and added some new tricks.

Today I dropped a quick compression module called Zippy

Let's see it in action and learn how it works.

Zippy Examples

# Compress a string using Brotli, output in base64
Compress-Zippy "Hello World"

Compress-Zippy "Hello Brotli" -Algorithm Brotli |
    Expand-Zippy -Algorithm Brotli

Compress-Zippy "Hello Deflate" -Algorithm Deflate |
    Expand-Zippy -Algorithm Deflate

Compress-Zippy "Hello GZip" -Algorithm GZip |
    Expand-Zippy -Algorithm GZip

Compress-Zippy "Hello ZLib" -Algorithm ZLib |
    Expand-Zippy -Algorithm ZLib

Compression in PowerShell

PowerShell is built on .NET, and .NET happens to have built-in support for four compression algorithms: Brotli, Deflate, GZip, and Zlib. We can compress data with any of these algorithms by using classes in the System.IO.Compression namespace, for example:

# Create a message
$message = "hello world"
# Get it as bytes
$bytes = $outputEncoding.GetBytes($message)
# Create a memory stream
$memoryStream = [IO.MemoryStream]::new()
# Create a compressor using the stream
$compressor = [IO.Compression.BrotliStream]::new(
     $memoryStream, [IO.Compression.CompressionLevel]::Fastest
)
# Write our bytes to the compressor
$compressor.Write($bytes,0, $bytes.Length)
# Close our compressor
$compressor.Close()
$compressor.Dispose()
# Get our compressed bytes
$compressedBytes = $memoryStream.ToArray()
# and output them
$compressedBytes

Decompression in PowerShell

Now let's go the other way around. It's easier.

# Create a new memory stream, containing our compressed bytes
$memoryStream = [IO.MemoryStream]::new($compressedBytes)
# Create a decompressed stream
$decompressedStream = [IO.Compression.BroitliStream]::new(
    $memoryStream, [IO.Compression.CompressionMode]::Decompress
)
# Create our output stream
$outputStream = [IO.MemoryStream]::new()
# Copy our decompressed stream to it
$decompressedStream.CopyTo($outputStream)
# Seek to the start (it outputs a position so null that out)
$null = $outputStream.Seek(0,'begin')
# Make a stream reader 
$streamReader = [IO.StreamReader]::new($outputStream, $outputEncoding)
# Read to the end, which will output our decompressed string
$streamReader.ReadToEnd()
# close up.
$streamReader.Close()

.NET and PowerShell

This has always been there, and it's pretty easy.

Both examples are less than 20 lines, with documentation.

These techniques are tried and true.

.NET has robust compression support because developers need to compress data all the time.

If we build on top of simple PowerShell and .NET, we build in a way that lasts a lifetime.

When I said "I dusted off some old code" for Zippy, I wasn't kidding.

Zippy is an update of the Compress-Data and Expand-Data functions in Pipeworks, the first attempt of PowerShell as a web language.

This is 16-year-old code, with minor updates made to support multiple compression algorithms and improved piping.

My only regret is that I didn't spin this off into its own module long ago

You can use this article as a guide to implementing your own compression, or you can use a little module like Zippy to get the job done.

Please enjoy this new addition to your PowerShell toolkit and have fun decompressing!


Log in to leave a note.