Creating Zero Filled Files with PowerShell

(Comments)

There are times where you'd like to create a dummy file for testing, if you're on Windows you may be familiar with the 'fsutil file createnew' command. This allows you to create a zero filled file of a predefined size, fantastic. It's a small, but powerful, command that is included with every Windows install but let's assume you need a PowerShell native method for creating a zero filled file, what might that look like?

 

This is my solution:


function Write-Zeros {
    param ([string]$Path, [uint64]$SizeBytes)
    begin {
        $fs = $null
        if ([System.IO.File]::Exists($Path)) { 
               $fs = New-Object System.IO.FileStream ($Path, [System.IO.FileMode]::Truncate) }
        else { $fs = New-Object System.IO.FileStream ($Path, [System.IO.FileMode]::OpenOrCreate)}
        if ($fs -like $null) { throw New-Object System.IO.IOException "Cannot create $Path" }
        if ($SizeBytes -gt 10MB) { Write-Warning "Async writes are memory allocated first,`n`t`t large writes may page to disk before writing to destination!" }
        $denom = 1KB
        for ($i=5; $i -gt 0; $i--) {
            if (($SizeBytes -gt 1MB) -and ($SizeBytes % ($i * 1MB) -eq 0)) {
                $denom = $i * 1MB
                break
            }
        }
        if ($i -eq 0) {
            $denom = 1KB
        }
        $bytes = New-Object Byte[] $denom
        $limit = $SizeBytes
        if ($limit -eq 0) { return }
    }
    process {
        try {
            $count = 0
            do {
                $fs.WriteAsync($bytes, 0, $denom) | Out-Null
                $count++
            } while (($count * $denom) -lt $limit) 
        }
        catch {
            throw
        }
        finally {
            $fs.Flush()
            $fs.Close()
        }
    }
}

 

It allows you to write out a file of specified length. Writes are dispatched asyncronously and write size varies based on the specified byte length, with larger writes being prefered if it evenly devides into the specified byte size. This allows you to create a large file using the PowerShell builtin size primitives: Write-Zeros "C:\temp\test.txt" 1GB so there's little manual math needed. While using fsutil is probably the right answer for almost any situation, consider that a PowerShell native function will throw exceptions rather than exit codes and an error stream to be parsed, and can be included in a scriptblock for remote invoke. Only relying on PowerShell and the underlying .Net runtime also frees your script from problems on machines with a trashed %PATH% environment variable (no, fully qualified paths to commands can't be trusted).

 

Recreating the wheel usually doesn't have a great value proposition but having a large library of portable PowerShell native operations makes more and more sense as that library grows. Enjoy.

Currently unrated

Comments