Commands/Read-OpenPackage.ps1
|
function Read-OpenPackage { <# .SYNOPSIS Reads Open Package Bytes .DESCRIPTION Reads Bytes within an Open Package .LINK Get-OpenPackage .LINK Write-OpenPackage .EXAMPLE $package = OP @{"hello.txt" = "Hello world"} $package | Read-OpenPackage -Uri /hello.txt .EXAMPLE $package = OP @{"hello.txt" = "Hello world"} ($package | Read-OpenPackage -Uri /hello.txt -RangeStart 0 -RangeEnd 5) -as 'char[]' .EXAMPLE $package = OP @{"hello.txt" = "Hello world"} ($package | Read-OpenPackage -Uri /hello.txt -RangeStart 0 -RangeEnd 5) -as 'char[]' -join '' #> [OutputType([byte[]])] [Alias('Read-OP', 'rdop', 'rdOpenPackage')] param( # One or more part uris [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [Alias('PartUri')] [Uri[]] $Uri, # A start range [Parameter(ValueFromPipelineByPropertyName)] [Alias('PartStart')] [long] $RangeStart, # An ending range [Parameter(ValueFromPipelineByPropertyName)] [Alias('PartEnd')] [long] $RangeEnd, # The input object. # If this is not a package, it will be passed thru. [Parameter(ValueFromPipeline)] [Alias('Package')] [PSObject] $InputObject ) process { # If the input was not a package, if ($InputObject -isnot [IO.Packaging.Package]) { return $InputObject # pass it thru. } # Read each part in the open package. foreach ($partUri in $uri) { # Make sure we have a leading slash $SlashPart = "$partUri" -replace '^/?', '/' # If the part does not exist if (-not $InputObject.PartExists($SlashPart)) { # continue to the next part. continue } # Try to get the part $part = $InputObject.GetPart($SlashPart) # if that failed, continue. if (-not $part) { continue } # If we do not have a range start and end if (-not $RangeStart -and -not $RangeEnd) { # look for a reader if ($part.Reader -and $part.Read) { # If we found one, $part.Read() # read the content continue # and continue. } # Otherwise, get our stream $partStream = $part.GetStream('Open', 'Read') # copy the output to a memory stream $memoryStream = [IO.MemoryStream]::new() $partStream.CopyTo($memoryStream) } else { # If a range was provided, get our stream $partStream = $part.GetStream('Open', 'Read') # If the range was smaller than the stream length if ($RangeStart -lt $partStream.Length) { # seek to the start of the range $null = $partStream.Seek($RangeStart, 'Begin') # and adjust the end if needed if ($rangeEnd -ge $partStream.Length) { $rangeEnd = $partStream.Length } # If the total range is positive if ($RangeEnd - $RangeStart -gt 0) { # get the range $buffer = [byte[]]::new($RangeEnd - $RangeStart) # read our byte range $bytesRead = $partStream.Read($buffer, 0, $buffer.Length) if ($bytesRead) { $memoryStream = [IO.MemoryStream]::new() # and write it to the memory stream $null = $memoryStream.Write($buffer,0 , $bytesRead) } } } else { # copy the output to a memory stream $memoryStream = [IO.MemoryStream]::new() $partStream.CopyTo($memoryStream) } } $partStream.Close() # Close our part stream $partStream.Dispose() # and dispose of it. # If we had a memory stream if ($memoryStream) { # get it as an array [byte[]]$partBytes = $memoryStream.ToArray() $memoryStream.Close() # then close $memoryStream.Dispose() # and dispose our stream. # and write the byte[] as a single object. $PSCmdlet.WriteObject($partBytes, $false) } } } } |