How do I change the below so i can use the Gzip data with [System.Convert]::ToBase64String() instead of an outfile then send THAT output(the b64) to an outfile
**I Received these answers from help on a previous post from an awesome member. It was marked as an answer but my goals were misunderstood.
Right now this does INFILE>Compress>OUTFILE, I want to do INFILE>Compress>Convert>OUTBase64
$infile = Get-Item path\to\myfiletocompress.ext
$instream = $infile.OpenRead()
$outstream = (New-Item path\to\mygzfile.gz).OpenWrite()
$gzip = [System.IO.Compression.GZipStream]::new(
$outstream,
[System.IO.Compression.CompressionLevel]::Optimal)
$instream.CopyTo($gzip)
$gzip.Dispose()
$outstream.Dispose()
$instream.Dispose()
And with this the reverse, I want to use Base64 for the input from a Var, and have that get converted from base64 first then get decompressed into an outfile.
This is currently INFILE>Decompress>OUTFILE I would like to INBase64>Convert>Decompress>OUTFILE
$infile = Get-Item path\to\mygzfile.gz
$instream = $infile.OpenRead()
$outstream = (New-Item path\to\myexpandedgzfile.ext -Force).OpenWrite()
$gzip = [System.IO.Compression.GZipStream]::new(
$instream,
[System.IO.Compression.CompressionMode]::Decompress)
$gzip.CopyTo($outstream)
$gzip.Dispose()
$outstream.Dispose()
$instream.Dispose()
The way I'm doing it now is with no compression, using IO.File ReadAllBytes, WriteAllBytes.
File>B64
[Convert]::ToBase64String([IO.File]::ReadAllBytes('anyfile.ext')) | Out-File 'anyfile.txt"
B64>File
[IO.File]::WriteAllBytes('anyfile.ext', [Convert]::FromBase64String('anyfile.txt'))
I tested the results of using gzip files instead of originals when encoding to B64 and the B64 encoded files were smaller than the originals, so this would be worth it.
EDIT: Using the below code with a temp file I can get a working result:
$filename = 'reflect_setup_free_x64.exe'
$infile = Get-Item $filename
$instream = $infile.OpenRead()
$outstream = (New-Item "$filename.gz").OpenWrite()
$gzip = [System.IO.Compression.GZipStream]::new(
$outstream,
[System.IO.Compression.CompressionLevel]::Optimal)
$instream.CopyTo($gzip)
$gzip.Dispose()
$outstream.Dispose()
$instream.Dispose()
[Convert]::ToBase64String([IO.File]::ReadAllBytes("$filename.gz")) | SC "$filename-encoded.txt" -NoNewline
But using the updated code in the solution gives me a larger file by min ~20%, something is wrong with it. Fails on decompression as well:
$content = Get-Content 'reflect_setup_free_x64.exe' -Raw
$outstream = [System.IO.MemoryStream]::new()
$gzip = [System.IO.Compression.GZipStream]::new(
$outstream,
[System.IO.Compression.CompressionLevel]::Optimal)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($content)
$gzip.Write($bytes, 0, $bytes.Length)
$gzip.Dispose()
# This is the b64 gzip string
[System.Convert]::ToBase64String($outstream.ToArray()) | SC 'reflectencoded.txt'
$outstream.Dispose()
And lasty I'm stuck on the reverse command to recreate the file from b64 ->->. This works with a temp file can you show me how to add the stream to this as well? Normally I can pick apart the answers and context to proceed on my own, but i do not understand this yet..
$filename ='reflect_setup_free_x64.exe'
$encoded = GC "$filename-encoded.txt"
[IO.File]::WriteAllBytes("$filename.gz", [Convert]::FromBase64String($encoded))
$infile = Get-Item "$filename.gz"
$instream = $infile.OpenRead()
$outstream = (New-Item "$filename" -Force).OpenWrite()
$gzip = [System.IO.Compression.GZipStream]::new(
$instream,
[System.IO.Compression.CompressionMode]::Decompress)
$gzip.CopyTo($outstream)
$gzip.Dispose()
$outstream.Dispose()
$instream.Dispose()
LAST EDIT - For the reverse process the below was used:
$filename ='reflect_setup_free_x64.exe'
$encoded = GC "$filename-encoded.txt"
$instream = [System.IO.MemoryStream]::new(
[Convert]::FromBase64String($encoded)
)
$outstream = (New-Item "$filename" -Force).OpenWrite()
$gzip = [System.IO.Compression.GZipStream]::new(
$instream,
[System.IO.Compression.CompressionMode]::Decompress)
$gzip.CopyTo($outstream)
$gzip.Dispose()
$outstream.Dispose()
$instream.Dispose()
You need to use a MemoryStream
instead of a FileStream
.
# `$content` could also be a hardcoded string here
$content = Get-Content path\to\file.txt -Raw
$outstream = [System.IO.MemoryStream]::new()
$gzip = [System.IO.Compression.GZipStream]::new(
$outstream,
[System.IO.Compression.CompressionLevel]::Optimal)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($content)
$gzip.Write($bytes, 0, $bytes.Length)
$gzip.Dispose()
$outstream.Dispose()
# This is the b64 gzip string
[System.Convert]::ToBase64String($outstream.ToArray())
$filename = 'reflect_setup_free_x64.exe'
$infile = Get-Item $filename
$instream = $infile.OpenRead()
$outstream = [System.IO.MemoryStream]::new()
$gzip = [System.IO.Compression.GZipStream]::new(
$outstream,
[System.IO.Compression.CompressionLevel]::Optimal)
$instream.CopyTo($gzip)
$gzip.Dispose()
$outstream.Dispose()
$instream.Dispose()
[Convert]::ToBase64String($outstream.ToArray()) |
Set-Content "$filename-encoded.txt" -NoNewline
You need to ensure that you will be using the same encoding to read this file back, as explained in previous answer, storing a gzip b64 string in a file (specially if it is a binary) doesn't make sense, [Convert]::ToBase64String(..)
should be out of this equation. Gzip b64 is mainly used for transport of data not for storage.
As aside, this process can be greatly simplified using the PSCompression
Module (Disclaimer: I'm the maintainer of this Module).
Using the module the first example translates to:
Get-Content path\to\file.txt -Raw | ConvertTo-GzipString
And the second example translates to:
$filename = Convert-Path 'reflect_setup_free_x64.exe'
$gzPath = $filename + '.gz'
Compress-GzipArchive $filename -Destination $gzPath
[System.Convert]::ToBase64String(
[System.IO.File]::ReadAllBytes($gzPath)) |
Set-Content "$filename-encoded.txt" -NoNewline