Thursday, May 8, 2008

Binary <-> Hex String files with Powershell

I needed a method of converting a text representation of a binary file (eg. the text 'AE00F00D' in a file) to the binary byte equivalent and vice versa.

Included are the PowerShell scripts I ended up writing for the task. The core parts of script are below, click 'Read More!' to see the full .PS1 scripts

Note that I have updated the original post, as the '-readcount 0' when reading the file, pre-allocating the array (thanks for the suggestion Phil) and using an assigned variable in the for loop made this much faster.


[byte[]]$bytes = Get-Content -encoding byte -readcount 0 -path $BinaryFile
  for ($i = 0; $i -le $count-1; $i++)
  { $hex = "{0:x}" -f $bytes[$i]
    [void]$output.Append($hex.PadLeft(2, "0"))  # Pad any single digits
  }
    set-content $OutputFile -value $output.ToString()

  $HexString = Get-Content -readcount 0 -path $HexStringFile
  for ( $i = 0; $i -le $count-1; $i+=2 )
  { $bytes[$x] = [byte]::Parse($hexString.Substring($i,2), [System.Globalization.NumberStyles]::HexNumber)
    $x += 1 }
    set-content -encoding byte $OutputFile -value $bytes



I was using this to restore and update some images stored in elements in an Operations Manager 2007 Management Pack XML file.


#HexStringToBinary.ps1

param(
   [string] $HexStringfile = "",
   [string] $OutputFile = ""
   )


if ($HexstringFile -ne "") {
  $HexString = Get-Content -readcount 0 -path $HexStringFile
  $HexString = $HexString[0]
  $count = $hexString.length
  $byteCount = $count/2
  $bytes = New-Object byte[] $byteCount
  $byte = $null

  $x = 0
  for ( $i = 0; $i -le $count-1; $i+=2 )
  { 
    $bytes[$x] = [byte]::Parse($hexString.Substring($i,2), [System.Globalization.NumberStyles]::HexNumber)
    $x += 1
  }

  if ($OutputFile -ne "") {
    set-content -encoding byte $OutputFile -value $bytes
  } else {
    write-host "No output file specified"
  }
} else{
  write-host "Error, no input file specified"
}

# Byte.Parse Method (String, NumberStyles)
# http://msdn.microsoft.com/en-us/library/4eszwye3(VS.80).aspx




#BinaryToHexString.ps1

param(
   [string] $Binaryfile = "",
   [string] $OutputFile = ""
   )

if ($BinaryFile -ne "") {
  [byte[]]$bytes = Get-Content -encoding byte -readcount 0 -path $BinaryFile # Use a readCount of 0 to read all lines at once

  $output = new-object System.Text.StringBuilder # Using stringBuilder seems faster than $a = $a + "a" ?
  $count = $bytes.length    # The loop seems much faster when using a pre-set value?
  for ($i = 0; $i -le $count-1; $i++)
  {
    $hex = "{0:x}" -f $bytes[$i]
    [void]$output.Append($hex.PadLeft(2, "0"))  # Pad any single digits
  }
  if ($OutputFile -ne "") {
    set-content $OutputFile -value $output.ToString()
  } else {
    write-host "No output file specified"
  }
} else{
  write-host "Error, no input file specified"
}

# .net formatting decimal to hex
# http://www.microsoft.com/technet/scriptcenter/topics/winpsh/convert/hex.mspx



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

2 comments:

Anonymous said...

Clever. It would be interesting to benchmark the text to binary conversion to see how well powershell can optimize things. The "[byte[]]$bytes = $bytes + $byte" part would just do hexString.length/2 memory allocations in C#, so I wonder if PowerShell is a bit cleverer on it's optimisations.

If not, would it be possible to preallocate the array, perhaps New-Object byte[] hexString.length/2 ? I wonder if it would even matter.

Anonymous said...

Thank you for the scripts!

Post a Comment