Created
July 25, 2024 17:24
-
-
Save Bill-Stewart/8dbb04ecbc0eb087b70d4e3b530603bc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Get-HexDump.ps1 | |
# Written by Bill Stewart (bstewart AT iname.com) | |
# Version history: | |
# | |
# 1.0 (2012-06-29) | |
# * Initial version. | |
# | |
# 1.1 (2017-03-24) | |
# * Slight performance improvement (don't keep recreating buffer). | |
# | |
# 1.2 (2019-11-12) | |
# * Standardize code formatting. | |
# | |
# 1.3 (2024-07-25) | |
# * Further standardization of code formatting. | |
#requires -version 2 | |
<# | |
.SYNOPSIS | |
Outputs the contents of a file as a hex dump. | |
.DESCRIPTION | |
Outputs the contents of a file as a hex dump. This is useful for viewing the content of a binary file. Characters outside the range of standard printable ASCII characters are output using a dot (.) by default. Use the -UnprintableChar parameter to specify a different character. | |
.PARAMETER Path | |
Specifies the path to a file. Wildcards are not permitted. The parameter name ("Path") is optional. | |
.PARAMETER UnprintableChar | |
Specifies the character to use for output of characters in the file that are outside of the standard printable ASCII character range. The default value is a dot ("."). | |
.PARAMETER BufferSize | |
Specifies the buffer size to use. The file will be read this many bytes at a time. This parameter must be a multiple of 16. The default is 65536 (64KB). | |
#> | |
param( | |
[Parameter(Position = 0,Mandatory)] | |
[String] | |
$Path, | |
[Char] | |
$UnprintableChar = ".", | |
[UInt32] | |
$BufferSize = 65536 | |
) | |
if ( -not (Test-Path -LiteralPath $Path) ) { | |
Write-Error "Path '$Path' not found." -Category ObjectNotFound | |
exit | |
} | |
$item = Get-Item -LiteralPath $Path -Force | |
if ( -not ($? -and ($item -is [IO.FileInfo])) ) { | |
Write-Error "'$Path' is not a file in the file system." -Category InvalidType | |
exit | |
} | |
if ( $item.Length -gt [UInt32]::MaxValue ) { | |
Write-Error "'$Path' is too large." -Category OpenError | |
exit | |
} | |
# The file will be output in 16-byte lines. | |
$bytesPerLine = 16 | |
if ( $BufferSize % $bytesPerLine -ne 0 ) { | |
Write-Error "-BufferSize parameter must be a multiple of $bytesPerLine." -Category InvalidArgument | |
exit | |
} | |
$ScriptName = $MyInvocation.MyCommand.Name | |
# Keep track of our position within the file. | |
[UInt32] $fileOffset = 0 | |
try { | |
$stream = [System.IO.File]::OpenRead($item.FullName) | |
$buffer = New-Object Byte[] $BufferSize | |
while ( $stream.Position -lt $stream.Length ) { | |
# Read $BufferSize bytes into $buffer, returning $bytesRead. | |
$bytesRead = $stream.Read($buffer,0,$BufferSize) | |
# Step through buffer $bytesPerLine bytes at a time. | |
for ( $line = 0; $line -lt [Math]::Floor($bytesRead / $bytesPerLine); $line++ ) { | |
# Grab 16-byte buffer slice, and create formatted string. | |
$slice = $buffer[($line * $bytesPerLine)..(($line * $bytesPerLine) + $bytesPerLine - 1)] | |
$hexOutput = "{0:X8} {01:X2} {02:X2} {03:X2} {04:X2} {05:X2} {06:X2} {07:X2} {08:X2} {09:X2} {10:X2} {11:X2} {12:X2} {13:X2} {14:X2} {15:X2} {16:X2} " -f (,$fileOffset + $slice) | |
# Create ASCII printable character output. | |
$charOutput = "" | |
foreach ( $byte in $slice ) { | |
if ( ($byte -ge 32) -and ($byte -le 126) ) { | |
$charOutput += [Char] $byte | |
} | |
else { | |
$charOutput += $UnprintableChar | |
} | |
} | |
"{0} {1}" -f $hexOutput,$charOutput | |
$fileOffset += $bytesPerLine | |
} | |
# Process bytes from end of file when file size not multiple of $bytesPerLine. | |
if ( $bytesRead % $bytesPerLine -ne 0 ) { | |
$slice = $buffer[($line * $bytesPerLine)..($bytesRead - 1)] | |
$hexOutput = "{0:X8} " -f $fileOffset | |
$charOutput = "" | |
foreach ( $byte in $slice ) { | |
$hexOutput += "{0:X2} " -f $byte | |
if ( ($byte -ge 32) -and ($byte -le 126) ) { | |
$charOutput += [Char] $byte | |
} | |
else { | |
$charOutput += $UnprintableChar | |
} | |
} | |
# PadRight needed to align the output. | |
"{0} {1}" -f $hexOutput.PadRight(58),$charOutput | |
} | |
Write-Progress -Activity $ScriptName ` | |
-Status ("Dumping file '{0}'" -f $item.FullName) ` | |
-PercentComplete (($fileOffset / $stream.Length) * 100) | |
} | |
} | |
catch [Management.Automation.MethodInvocationException] { | |
throw $_ | |
} | |
finally { | |
$stream.Close() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment