【问题标题】:Write bytes to a file natively in PowerShell在 PowerShell 中本机将字节写入文件
【发布时间】:2020-12-14 09:01:07
【问题描述】:

我有一个用于测试返回 base64 编码图像的 API 的脚本。我目前的解决方案是这样的。

$e = (curl.exe -H "Content-Type: multipart/form-data" -F "image=@clear.png" localhost:5000)
$decoded = [System.Convert]::FromBase64CharArray($e, 0, $e.Length)
[io.file]::WriteAllBytes('out.png', $decoded) # <--- line in question

Get-Content('out.png') | Format-Hex

这可行,但我希望能够在 PowerShell 中本地编写字节数组,而不必从 [io.file] 获取源代码。

我的 尝试在 PowerShell 中写入 $decoded 都导致写入 integer 字节值的字符串编码列表。 (例如)

42
125
230
12
34
...

你如何正确地做到这一点?

【问题讨论】:

  • 你已经做得很好了。 [IO.File]::WriteAllBytes() 是在 PowerShell 中将字节写入文件的正确方法。
  • 为什么您不想在 Powershell 中“本地”编写? PS 或多或少是建立在 .Net 之上的,所以使用 .Net 方法是非常好的和标准的。
  • 不确定,请随时纠正我,但我认为您的问题可能更恰当地表述为 How do you do this with PowerShell Cmdlets? -- my ~28¢
  • 我认为“惯用”是您要寻找的形容词,而不是“本机”。
  • @thomasb 我知道这是旧的,但有些人想在 powershell 中不使用 IO.File 编写的原因是使用 IO.File 在 Powershell 受限模式下不起作用,这在某些高安全环境。不过,下面接受的答案将在受限模式下工作。

标签: powershell


【解决方案1】:

Set-Content cmdlet 允许您使用 Byte 编码将原始字节写入文件:

$decoded = [System.Convert]::FromBase64CharArray($e, 0, $e.Length)
Set-Content out.png -Value $decoded -Encoding Byte

(但是,BACON 在评论中指出 Set-Content 很慢:在测试中,写入 10 MB 数据需要 10 秒和 360 MB 的 RAM。所以,我建议不要使用 Set - 如果这对您的应用程序来说太慢了,请提供内容。)

【讨论】:

  • 一个惯用(和高级)的解决方案。
  • 为什么这么慢?写入 14 兆字节需要 2 多分钟。
  • @Sasha,它很慢,因为有 1400 万字节通过管道传递,一次一个字节。关于管道性能的详细信息*.com/questions/34113755/…
  • @jimhark 考虑到这一点,这个答案似乎应该包括(如果不推荐)将其写为Set-Content out.png -Value $decoded -Encoding Byte。使用Measure-Command 和任务管理器对 10 MB 数组的两次调用进行快速基准测试,$byteArray | Set-Content ... -Encoding Byte 需要 3 分钟/+5.5 GB RAM,而 PS5.1 中Set-Content ... -Value $byteArray -Encoding Byte 需要 10 秒/+360 MB RAM;一个很大的进步,但仍然很糟糕。在 PS7 上使用 -AsByteStream 可使流水线速度快 45 秒,但与 -Value没有区别。如果可能的话,我会说避免Set-Content
  • @TannerSwett, -Encoding Bytereplaced 与 PowerShell 中的 -AsByteStream6
【解决方案2】:

运行 C# 程序集是 PowerShell 本机的,因此您已经“本机”将字节写入文件。

如果你坚持,你可以使用像set-content test.jpg -value (([char[]]$decoded) -join "") 这样的结构,这有一个缺点是在写入数据的末尾添加#13#10。使用 JPEG 是可以忍受的,但其他文件可能会因这种更改而损坏。所以请坚持使用 .NET 的字节优化例程,而不是搜索“本机”方法——这些已经是本机了。

【讨论】:

    【解决方案3】:

    Powershell Core(v6 及更高版本)不再有 -Encoding byte 作为选项,因此您需要使用 -AsByteStream,例如:

    Set-Content -Path C:\temp\test.jpg -AsByteStream
    

    【讨论】:

    • -缺少值参数。正确的命令是:Set-Content -Path 'out.png' -Value $decoded -AsByteStream;