I need to compress a string to Zlib in PowerShell.
Is there a way we can compress using the ZLibStream class in PowerShell?
https://learn.microsoft.com/en-us/dotnet/api/system.io.compression.zlibstream?view=net-8.0
I was able to compress using the class DeflateStream
and GZipStream
, but the external system which uses the data was not able to decode it.
This is the powershell script I tried with
$stringToCompress = 'string to compress'
$memStream = New-Object System.IO.MemoryStream
$deflateStream = New-Object System.IO.Compression.GZipStream($memStream, [System.IO.Compression.CompressionMode]::Compress)
$streamWriter = New-Object System.IO.StreamWriter($deflateStream)
$streamWriter.Write($stringToCompress)
$streamWriter.Close();
$encodedCompressedString = [System.Convert]::ToBase64String($memStream.ToArray())
Write-Output $encodedCompressedString
The process of compression and expansion with ZLibStream
is pretty much the same as with GZipStream
.
Note that ZlibStream
only works with .NET 6+ meaning that it is not available for Windows PowerShell 5.1 (.NET Framework 4.5+). If you want to use this class you will need to install PowerShell 7+.
# Choose encoding here, need to use the same for compress & decompress
$enc = [System.Text.Encoding]::UTF8
# - Compress:
$string = 'hello world!'
$outstream = [System.IO.MemoryStream]::new()
$zlib = [System.IO.Compression.ZLibStream]::new(
$outstream,
[System.IO.Compression.CompressionMode]::Compress)
$bytes = $enc.GetBytes($string)
$zlib.Write($bytes, 0, $bytes.Length)
$zlib.Dispose()
[System.Convert]::ToBase64String($outstream.ToArray())
# eJzLSM3JyVcozy/KSVEEAB6JBH4=
# - Decompress:
$instream = [System.IO.MemoryStream]::new(
[System.Convert]::FromBase64String('eJzLSM3JyVcozy/KSVEEAB6JBH4='))
$zlib = [System.IO.Compression.ZLibStream]::new(
$instream,
[System.IO.Compression.CompressionMode]::Decompress)
$outstream = [System.IO.MemoryStream]::new()
$zlib.CopyTo($outstream)
$zlib.Dispose()
$enc.GetString($outstream.ToArray())
# hello world!
An alternative for Windows PowerShell 5.1 can be to use the ZLibWrapper
package.
First download the package and expand it:
$invokeWebRequestSplat = @{
OutFile = 'Joveler.ZLibWrapper.zip'
Uri = 'https://www.nuget.org/api/v2/package/Joveler.ZLibWrapper'
}
Invoke-WebRequest @invokeWebRequestSplat
Expand-Archive 'Joveler.ZLibWrapper.zip'
Then the flow is pretty similar using their assembly:
Add-Type -Path .\Joveler.ZLibWrapper\lib\net45\Joveler.ZLibWrapper.dll
# Choose encoding here, need to use the same for compress & decompress
$enc = [System.Text.Encoding]::UTF8
# - Compress:
$string = 'hello world!'
$outstream = [System.IO.MemoryStream]::new()
$zlib = [Joveler.ZLibWrapper.ZlibStream]::new(
$outstream,
[Joveler.ZLibWrapper.ZLibMode]::Compress)
$bytes = $enc.GetBytes($string)
$zlib.Write($bytes, 0, $bytes.Length)
$zlib.Dispose()
[System.Convert]::ToBase64String($outstream.ToArray())
# - Decompress:
$instream = [System.IO.MemoryStream]::new(
[System.Convert]::FromBase64String('eJzLSM3JyVcozy/KSVEEAB6JBH4='))
$zlib = [Joveler.ZLibWrapper.ZLibStream]::new(
$instream,
[Joveler.ZLibWrapper.ZLibMode]::Decompress)
$outstream = [System.IO.MemoryStream]::new()
$zlib.CopyTo($outstream)
$zlib.Dispose()
$enc.GetString($outstream.ToArray())
# hello world!