2

I have a large VMDK file that has to be broken down into smaller segments to send via website. I have the scripting down to where I split the VMDK into 2GB increments for a total of 30 files. I then put the files together in a string. My problem is taking the string and delimiting it into groups of four and sending them into multiple zip file (website has an 8GB transfer limit). I'm not sure if using and array would be an easier option. New at using Powershell so any advice is welcome.

This is the script I have so far.

function Split-File 
{
    $inFile = "C:\Users\Justin\Desktop\Split_Test\disk1.vmdk"

    ([Long]$bufSize = 2000mb)
    $stream = [System.IO.File]::OpenRead($inFile)
    $chunkNum = 1
    $barr = New-Object byte[] $bufSize

    $fileinfo = [System.IO.FileInfo]$inFile
    $name = $fileinfo.Name
    $dir = $fileinfo.Directory

    while ($bytesRead = $stream.Read($barr, 0, [Long]$bufsize)) {
        $outFile = Join-Path $dir "$name.part$chunkNum"
        $ostream = [System.IO.File]::OpenWrite($outFile)
        $ostream.Write($barr, 0, $bytesRead)
        $ostream.Close()
        Write-Host "Wrote $outFile"
        $chunkNum += 1
    }
    $stream.Close()
}
Split-File

I then put the output files into a string using.

$Split = Get-ChildItem C:\Users\Justin\Desktop\Split_Test | Where-Object {$_.Extension -ne ".ps1"}
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Note that ```$stream.Read``` doesn’t guarantee to read ```count``` bytes even if that many are available, so you aren’t guaranteed to be breaking your file into 2000mb chunks - they could be a whole lot smaller if ```$stream.Read``` were to return the file contents in, for example, 1mb chunks. You need an inner loop really for each chunk to keep reading until you hit your max chunk size or ```$stream.Read``` returns 0. See https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.read?view=net-7.0#system-io-stream-read(system-byte()-system-int32-system-int32) – mclayton Jan 11 '23 at 21:27
  • 1
    @mclayton, I haven't tested, but to me the linked docs seem to imply that as many bytes as requested _are_ read _if available_, and for a preexisting file "at rest" _all_ bytes should be available. – mklement0 Jan 11 '23 at 23:01
  • If I'm understanding correctly, instead of `$ostream.Write($barr, 0, $bytesRead)` to file you could write the bytes to a WrappedStream (an Entry on a ZipArchive) but I'm not sure that's what you're looking for. If so, your code would need just a tiny modification. – Santiago Squarzon Jan 11 '23 at 23:06
  • 1
    @mklement0 I think you're right – Santiago Squarzon Jan 11 '23 at 23:07
  • 1
    It looks like your problem can be reduced to partitioning an array of file paths into chunks of 4. If so, [this answer](https://stackoverflow.com/a/58352033/45375) may help. – mklement0 Jan 11 '23 at 23:47
  • 1
    @mklement0 - possibly. I think the docs are a little bit ambiguous - for example at the bottom of the remarks it says “An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached.” (without mentioning if there are available bytes or not). On the few occasions I’ve needed to use ```stream.Read``` I’ve alway erred on the side of caution and used a “pump” like in the example in the docs… – mclayton Jan 12 '23 at 07:55

0 Answers0