powershell 将文件转换为Gzip内存流,然后在导出为文本文件(或var)之前将其转换为Base64

y3bcpkx1  于 2023-10-18  发布在  Shell
关注(0)|答案(1)|浏览(140)

我如何改变下面的,所以我可以使用Gzip数据与[System.Convert]::ToBase 64 String()而不是一个outfile然后发送那个输出(b64)到一个outfile

**我收到了这些答案从帮助上一篇文章从一个真棒成员。它被标记为答案,但我的目标被误解了。

现在执行INFILE>Compress>OUTFILE,我想执行INFILE>Compress>Convert> OUTBase 64

$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()

反过来,我想使用Base64作为Var的输入,首先从Base64转换,然后解压到outfile中。
当前为INFILE>Decompress>OUTFILE我想INBase 64>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()

我现在做的方法是不压缩,使用IO。文件ReadAllBytes,WriteAllBytes。
文件>B64

[Convert]::ToBase64String([IO.File]::ReadAllBytes('anyfile.ext')) | Out-File 'anyfile.txt"

B64>文件

[IO.File]::WriteAllBytes('anyfile.ext', [Convert]::FromBase64String('anyfile.txt'))

我测试了在编码到B64时使用gzip文件而不是原件的结果,B64编码的文件比原件小,所以这是值得的。

编辑:使用下面的代码和一个临时文件,我可以得到一个工作结果:

$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

但是在解决方案中使用更新的代码会使文件变大至少20%,这是有问题的。解压缩也失败:

$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()

最后,我被困在反向命令从b64 ->->重新创建文件。这是一个临时文件,你能告诉我如何添加流到这一点?通常我可以把答案和上下文分开来自己进行,但我还不明白这一点。

$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()

最后编辑-对于相反过程,使用以下内容:

$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()
dy1byipe

dy1byipe1#

您需要使用MemoryStream而不是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

你需要确保你将使用相同的编码来读回这个文件,正如前面的答案所解释的那样,在文件中存储gzip b64字符串(特别是如果它是二进制文件)没有意义,[Convert]::ToBase64String(..)应该不在这个等式中。Gzip b64主要用于数据传输,而不是存储。
另外,使用PSCompression Module可以大大简化此过程(* 免责声明:* 我是此模块的维护者 *)。
使用模块,第一个示例可以翻译为:

Get-Content path\to\file.txt -Raw | ConvertTo-GzipString

第二个例子可以翻译成:

$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

相关问题