Search code examples
arrayspowershelltype-conversionsigned

Is it possible to convert a byte array to a 8-bit signed integer array in Powershell?


I am trying to convert a Hex string to an 8-bit signed integer array in Powershell.

I am using the following function to convert a Hex string, such as A591BF86E5D7D9837EE7ACC569C4B59B, to a byte array which I then need to convert to a 8-bit signed integer array.

Function GetByteArray {

    [cmdletbinding()]

    param(
        [parameter(Mandatory=$true)]
        [String]
        $HexString
    )

    $Bytes = [byte[]]::new($HexString.Length / 2)

    For($i=0; $i -lt $HexString.Length; $i+=2){
        $Bytes[$i/2] = [convert]::ToByte($HexString.Substring($i, 2), 16)
    }

    $Bytes  
}

After using the function the hex is converted to a byte array such as this:

unsigned byte array

I need to take the unsigned byte array and convert o to 8bit signed byte array, like the one below:

signed 8-bit integer array (byte array)

Is this possible? If so how can it be implemented?

I've tried using the BitConverter class but, as far as I saw, it can only convert to int16.

Thanks in advance


Solution

  • To get a [byte[]] array ([byte] == System.Byte, an unsigned 8-bit integer type):

    $hexStr = 'A591BF86E5D7D9837EE7ACC569C4B59B' # sample input
    
    [byte[]] -split ($hexStr -replace '..', '0x$& ')
    
    • -replace , '..', '0x& ' inserts 0x before each pair (..) of hex digits and inserts a space afterwards, yielding string '0xA5 0x91 ... '

    • -split applied to the resulting string splits the string by whitespace into an array of individual byte representations ('0xA5', '0x91', ...)

    • casting the result to [byte[]] helpfully recognizes this hex format directly.

      • Note: If you forget the cast, you'll get an array of strings.
    • To get an [sbyte[]] array ([sbyte] == System.SByte, a signed 8-bit integer), cast directly to [sbyte[]] instead; do not try to combine the casts: [sbyte[]] [byte[]] (...))

    Simpler PowerShell (Core) 7.1+ alternative, using the .NET 5+ [System.Convert]::FromHexString() method:

    $hexStr = 'A591BF86E5D7D9837EE7ACC569C4B59B' # sample input
    
    # Directly returns a [byte[]] array.
    # Cast to [sbyte[]] if you need [sbyte] instances.
    [System.Convert]::FromHexString($hexStr)
    

    If you're given a [byte[]] array that you then want to convert to [sbyte[]], use the following (there may be more efficient approaches):

    [byte[]] $bytes = 0x41, 0xFF # sample input; decimal: 65, 255
    
    # -> [sbyte] values of:  65, -1
    [sbyte[]] $sBytes = $bytes.ForEach('ToString', 'x') -replace '^', '0x'
    

    Applied to your sample values, in decimal notation:

    # Input array of [byte]s.
    [byte[]] $bytes = 43, 240, 82, 109, 185, 46, 111, 8, 164, 74, 164, 172
    # Convert to an [sbyte] array.
    [sbyte[]] $sBytes = $bytes.ForEach('ToString', 'x') -replace '^', '0x'
    $sBytes # Output (each signed byte prints on its own line, in decimal form).
    

    Output:

    43
    -16
    82
    109
    -71
    46
    111
    8
    -92
    74
    -92
    -84