如何从PowerShell中的外部命令输出获取原始二进制数据?

时间:2017-10-26 06:23:52

标签: shell powershell encoding pipeline

我在这里读到,当您在powershell中运行外部命令时,它们的输出始终被解释为字符串或字符串数​​组:https://stackoverflow.com/a/35980675/983442

我正在尝试从外部命令处理二进制输出,但似乎PowerShell只能给我字符串。

这让我想知道,用什么编码将二进制数据转换成字符串?而且,它如何解释换行符以便将二进制数据划分为字符串数组?它似乎只在\n字符上分裂,但我确信它也会在\r\n上分裂。

是否有一种可靠的方法来获取字符串powershell给我并将它们转回字节数组?

例如,假设我有一个包含以下内容的批处理文件,称之为thing.bat

@echo off
type image.jpg

然后我运行以下powershell:

PS> $x = & .\thing.bat
PS> $x.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS> $x[0].gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS> $x.count
36

如果我有$x变量,怎么能在PowerShell中可靠地重新创建这个image.jpg?

1 个答案:

答案 0 :(得分:1)

PowerShell假设,您调用的每个外部程序仅提供string个输出流。 虽然距离现实还不远,但人们可能希望从外部程序中获取实际字节。 为实现这一目标,我们将从零开始创建一个新流程"

$procInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{
    FileName = "cmd.exe"
    Arguments = "thing.bat"
    RedirectStandardError = $true
    RedirectStandardOutput = $true
    UseShellExecute = $false
}
$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $procInfo
$proc.Start() | Out-Null
$proc.WaitForExit()

当相应的重定向属性设置为StandardOutput时,为StandardError$true提供了StreamReader

现在要获取信息流的内容,我们可以轻松使用$outContent = $proc.StandardOutput.ReadToEnd() Read Method int Read(), int Read(char[] buffer, int index, int count) ReadAsync Method System.Threading.Tasks.Task[int] ReadAsync(char[] buffer, int index, int count) ReadBlock Method int ReadBlock(char[] buffer, int index, int count) ReadBlockAsync Method System.Threading.Tasks.Task[int] ReadBlockAsync(char[] buffer, int index, int count) ReadLine Method string ReadLine() ReadLineAsync Method System.Threading.Tasks.Task[string] ReadLineAsync() ReadToEnd Method string ReadToEnd() ReadToEndAsync Method System.Threading.Tasks.Task[string] ReadToEndAsync() ,但这样会再次给我们一个字符串。

A ReadToEnd()为我们提供了以下方法(其中包括):

char[]

只需创建$length = $proc.StandardOutput.Length $s = New-Object 'char[]' $length $proc.StandardOutput.Read($s, 0, $length - 1) 缓冲区并将其传递给StreamReader,然后按照您的意愿使用它:

-Encoding Oem

第二种 - 更容易但不太灵活的解决方案:

如果您在将文件写入磁盘时遇到问题,可以轻松地将程序的标准输出重定向到Get-Content的文件,然后使用& .\thing.bat | Out-File -FilePath "C:/tmp/out.txt" -Encoding Oem $rawContent = Get-Content -Path "C:/tmp/out.txt" -Encoding Oem 再次阅读:

import java.util.Scanner;

public class rthji {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int num = 0;
        int num1 = 0;
        int num2 = 0;
        int num3 = 0;
        int num4 = 0;
        int num5 = 0;

        System.out.println("Insert the length of the small side of the triangle");
        num = in.nextInt();
        System.out.println("Insert the length of the big of the triangle");
        num1 = in.nextInt();
        System.out.println("Insert the length of the last side of the triangle");
        num2 = in.nextInt();

        for (int i = 1; 1 >= 10; i++) {

            System.out.println("Insert the length of the small side of the triangle");
            num3 = in.nextInt();
            System.out.println("Insert the length of the big of the triangle");
            num4 = in.nextInt();
            System.out.println("Insert the length of the last side of the triangle");
            num5 = in.nextInt();
            if (num3 * num3 + num5 * num5 != num4 * num4) {
                num3 = num4 = num5 = 0;
            } else if (num3 > num && num1 < num4 && num2 < num5) {
                num = num3;
                num1 = num4;
                num2 = num5;
            }
            System.out.println("The ribs of the largest triangle are:" + num1 + (",") + num2 + (",") + num3);
        }
    }
}