在PowerShell中解析二进制数据

时间:2018-01-03 21:40:30

标签: powershell typecasting-operator

我已经将二进制文件的内容读作无符号字节数组,但我想将其中的一些解释为有符号字节。我该怎么做?

#An array of unsigned bytes
[byte[]]$b = @(255)
#This doesn't work
[sbyte]$s = $b[0]
#Neither does this
[sbyte]$s = [convert]::ToSByte($b[0])

我想要的是价值-1

1 个答案:

答案 0 :(得分:1)

如果value大于[sbyte]::MaxValue

The \[System.Convert\]::ToSByte(value) method会引发 OverflowException

回归理论(Converting from two's complement representation):

$mask = [byte]  0x80    # [math]::pow(2,7)
$b    = [byte]  255
$s    = [sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )

'result: {0,4}, {1,4} ( = 0x{0:x2}, 0x{1:x2} )' -f $b, $s

输出:

result:  255,   -1 (= 0xff, 0xff )

当然,您可以将计算简化为

$s    = [sbyte] ( -($b -band 0x80) + ($b -band 0x7F) )

修改 以反驳PetSerAl's doubts关于[sbyte] -($b -band $mask) + ($b -band ( -bnot $mask ))公式正确性的问题。 PetSerAl's doubts是对的:Powershell-ISE的结果与Powershell中的结果不同!该公式应该是(见标记括号)

#       ↓                                                ↓
[sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
#       ↑                                                ↑

<强>证明

function AsSignedByte {     ### taken from PetSerAl's comment to the OQ
    param([Byte]$Byte) 
    [sbyte]$( if($Byte -ge 128) { $Byte - 256 } else { $Byte }) 
}

$mask = [byte]  0x80    # [math]::pow(2,7)
$good = 0
For ($i  = 0 ; $i -lt 256; $i++) {
    $b    = [byte]  $i
    $s    = [sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
    $ss   = AsSignedByte $b 
    if ( ($s -ne $ss) -or 
         ($s.GetTypeCode() -ne $ss.GetTypeCode()) -or 
         ($s -isnot [sbyte])) {
        'result: {0,4}, {1,4} ( = 0x{0:x2}, 0x{1:x2} )' -f $s, $ss
    } else { 
        $good +=1
    }
}
$good

<强>输出

PS D:\PShell> D:\PShell\SO\48085510.ps1
256

PS D:\PShell>