Hey, Scripting Guy! How Can I Use Windows PowerShell 2.0 to Create a Text File of a Specific Size?

Hey, Scripting Guy! How Can I Use Windows PowerShell 2.0 to Create a Text File of a Specific Size?

  • Comments 3
  • Likes

 

Bookmark and Share

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I need to be able to use Windows PowerShell 2.0 to create a text file that is a specific size. I know that I can create a text file by using FSUTIL, but when I open the file, it is empty. Therefore, I would like a text file that contains a certain amount of data inside it. The reason for this request is I need to troubleshoot a router that I suspect is dropping packets when a file is being copied beyond a certain size. Can you help?

-- RN

 

Hey, Scripting Guy! AnswerHello RN,

Microsoft Scripting Guy Ed Wilson here. As you may or may not know, we are in our final week of reviewing the 2010 Scripting Games. As it just so happens, Advanced Event 8 contained a task that required participants to create a text file of a specific size. Lee Holmes, one of the developers of Windows PowerShell and author of an excellent book on Windows PowerShell, wrote the expert commentary for the event. For a VBScript approach to the problem, refer to the script by Jakob Gottlieb Svendsen, MCT extraordinaire from Denmark, in the same article.

I thought I would review a script written by Bruno for the event. It begins by using the Windows PowerShell 2.0 help tags to plug the script into the Windows PowerShell help system. This means you can use Get-Help to figure out how the script works. This is shown here:

PS C:\> Get-Help C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8_Bruno.ps1

NAME

C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8_Bruno.ps1

SYNOPSIS

Creates text files of specific sizes

SYNTAX

C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8_Bruno.ps1 [[-text] <Object>] [[-sizes

] <Object>] [[-folder] <Object>] [<CommonParameters>]

DESCRIPTION

This script can be used to create test (and text) files of specific sizes,

such as 1 MB. The text that will appear in each file is configurable via a

command-line parameter, as well as the sizes of the files and the folder

where the files should be created. If called with no arguments, four files with

sizes 100 MB, 1 MB, 10 MB, and 100 MB will be created in the current folder.

RELATED LINKS

REMARKS

To see the examples, type: "get-help C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8_

Bruno.ps1 -examples".

For more information, type: "get-help C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8

_Bruno.ps1 -detailed".

For technical information, type: "get-help C:\data\ScriptingGuys\2010\HSG_6_7_10

\ADV8_Bruno.ps1 -full".

PS C:\>

 

You can also use the Get-Help cmdlet to return only the examples, as shown here:

PS C:\> Get-Help C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8_Bruno.ps1 -Examples

NAME

C:\data\ScriptingGuys\2010\HSG_6_7_10\ADV8_Bruno.ps1

SYNOPSIS

Creates text files of specific sizes

-------------------------- EXAMPLE 1 --------------------------

C:\PS>.\Advanced8.ps1 -Sizes 10 KB, 50 KB

Creates text files of sizes 10 KB and 50 KB in the current folder

-------------------------- EXAMPLE 2 --------------------------

C:\PS>.\Advanced8.ps1 -Text 'Just testing...' -Sizes 10kb -Folder C:\fso

Creates a 10 KB file with the text 'Just testing...' in the C:\fso folder.

PS C:\>

The use of the Help tags in conjunction with a script or a function is a Windows PowerShell best practice that vastly simplifies the creation of help information for your scripts. Another thing that Bruno does in the ADV8_Bruno.ps1 script to make his script easier to use is he assigns default values for each of the parameters. This means you run the script without the need to supply any input to it. The possible area for improvement in the script is that it does not check the current location. It is possible the working directory could be the root of the drive, or even one of the Windows directories to which a user might not have access. A quick check for permission to write to the directory would be an improvement. Or you could simply exclude the root and any Windows directory from use. The param statement with the default values is shown here:

param(
$text = "2010 Scripting Games: Advanced Event 8--Creating Text Files of Specific Sizes`n",
$sizes = (100kb, 1mb, 10mb, 100mb),
$folder = "."
)

The script is divided into functions to make it easy to read and understand. For example, there is a function that Bruno reused from his ADV5 script to perform the conversion for the file size units. The main function called CreateFile uses the Out-File cmdlet to add the text to the desired text files. By using the Out-File cmdlet Bruno is able to specify ASCII text, which is 1 byte per character. This section of the function is seen here:

Out-File -InputObject $finalText -encoding ASCII `
-filepath (Join-Path $_folder $fileName)

It is great that he uses the Join-Path cmdlet to create the path to the destination file. A couple of things would improve the function. The first is the name itself. He calls it CreateFile – which is a verb / noun combination, but he does not use the naming convention of Windows PowerShell. The function could be called Create-File and it would not generate a warning message if he later decides to incorporate it into a module. In addition, the parameters for the function are implemented in the same way that they were done in VBScript. It is a best practice to use the Param statement instead of the following code:

function createFile($_text, $_size, $_folder = '.') {

It would be better if it were written like this:

Function Create-File

{

Param(

[string]$text,

[string]$size,

[string]$folder = “.”

) #end param

} #end function Create-File

One last improvement to the script would be to add a comment indicating the entry point to the script. In a quick scan of the script, it is hard to see where the CreateFile function ends, and where the execution of the script begins. This is how I like to make the entry point indication in my scripts:

...

Out-File -InputObject $finalText -encoding ASCII `

-filepath (Join-Path $_folder $fileName)

} #end function CreateFile

# *** ENTRY POINT TO SCRIPT ***

# Creates files with the listed sizes

foreach ($size in $sizes) {

createFile $text $size $folder

} #end foreach

The complete ADV8_Bruno.ps1 script is shown here.

ADV8_Bruno.ps1

<#
.Synopsis
Creates text files of specific sizes
.Description
This script can be used to create test (and text) files of specific sizes,
such as 1 MB. The text that will appear in each file is configurable via a
command-line parameter, as well as the sizes of the files and the folder
where the files should be created. If called with no arguments, four files with
sizes 100 KB, 1 MB, 10 MB and 100 MB will be created in the current folder.
.Parameter Text
The text that will be inside the created files. In order to create a file
with the exact required size, the last line of the file may contain only a
portion of this string.
.Parameter Sizes
An array of integers containing the sizes of the files to be created.
One file will be created for each size specified. You can use a unit
notation, such as 100 MB.
.Parameter Folder
The folder where the files will be created. The default is the current
folder.
.Example
C:\PS> .\ADV8_Bruno.ps1 -Sizes 10kb, 50kb
Creates files of sizes 10 KB and 50 KB in the current folder
.Example
C:\PS> .\ADV8_Bruno.ps1 -Text 'Just testing...' -Sizes 10kb -Folder C:\fso
Creates a 10 KB file with the text 'Just testing...' in the C:\fso folder.
.Notes
2010 Scripting Games
Advanced Event 8--Creating Text Files of Specific Sizes
Author: Bruno L Fugisawa Gomes
Name: ADV8_Bruno.ps1
#>
param(
$text = "2010 Scripting Games: Advanced Event 8--Creating Text Files of Specific Sizes`n",
$sizes = (100kb, 1mb, 10mb, 100mb),
$folder = "."
)
# Borrowed from my Advanced 5 script.
# A not too fancy way to convert file size to an appropriate unit.
# Should work for a few years, because it already supports terabytes ;)
function convertSizeUnit($_size) {
switch ($_size)
{
{ $_ -ge 1TB } { $sizeText = "$($_/1TB)T"; break;}
{ $_ -ge 1GB } { $sizeText = "$($_/1GB)G"; break;}
{ $_ -ge 1MB } { $sizeText = "$($_/1MB)M"; break;}
{ $_ -ge 1KB } { $sizeText = "$($_/1KB)K"; break;}
default {$sizeText = "${_}B"}
}
return $sizeText
}
# Function creates a file with a given size using the text passed as parameter
function createFile($_text, $_size, $_folder = '.') {
# The total char length should be the desired file size minus 2, because an
# empty file seems to have 2 bytes, for some reason. Note that we will use
# ASCII encoding, which means 1 char = 1 byte.
$charLength = $_size - 2
# Assuring the string ends with one carriage return/new line
# (just to make the file look nicer).
$_text = $_text.trim() + "`r`n"
# Calculating how many times we should repeat the text
$div = [Math]::Truncate($charLength / $_text.Length)
# We most likely will need to repeat only a portion of the text to achieve
# the desired size
$remainder = $charLength % $_text.Length
if ($remainder -gt 0) {
# Yep, we will need to pad the file with a few characters from the text
# to make the size exact. Who would've thought?
$finalText = $_text * $div + ($_text[0..($remainder - 1)] -join '')
} else {
# Wow, the text fits perfectly to the desired size!
$finalText = $_text * $div
}
# Creating the filename according to the size unit
$fileName = "TestFile" + (convertSizeUnit $_size) + ".txt"
# Now we create the file using ASCII encoding (1 byte per char)
Out-File -InputObject $finalText -encoding ASCII `
-filepath (Join-Path $_folder $fileName)
}
# Creates files with the listed sizes
foreach ($size in $sizes) {
createFile $text $size $folder
}

When the script runs, no feedback is provided on the Windows PowerShell console, as shown in the following image. To let the user know which files were created and where they can be found, I might be tempted to write feedback such as completepath filename size of file was created. This is especially true because the script can be run without any inputs, and the user may wonder where to find the newly created files.

Image of no feedback on Windows PowerShell console when script is run

As shown in the following image, the newly created files reside in the c:\fso folder, which was the working directory I set as shown in the previous image.

Image of files in c:\fso folder

As shown in the following image, the TestFile5M.txt file is exactly 5 MB in size.

Image of TestFile5M.txt file being 5 MB in size

The newly created files contain the text that was specified for the –text parameter. I took the defaults when creating the files, as shown in the following image.

Image of text file content

RN, that is all there is to using Windows PowerShell 2.0 to create a text file that is a specific size. The 2010 Scripting Games Wrap-Up Week 2 will continue tomorrow.

 

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson and Craig Liebendorfer, Scripting Guys

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi, i had created a power shell script but the output is saving in text pad/note pad.I want the output in .data format..You could help me out.Thanks in advance

  • Code crashes once file sized get up into the 1+ GB range (depending on system memory) I changed the code to page out to the outfile in 10mb chunks for my purposes. (I didn't need exact byte size files, just giant text files)

    $chunksize = 10mb

    foreach ($size in $sizes)
    {
    # Assuring the string ends with one carriage return/new line
    # (just to make the file look nicer).
    $text = $text.trim() + "`r`n"

    # Calculating how many times we should repeat the text to make a chunk
    $numLinesToMakeChunk = [Math]::Truncate($chunksize / $text.Length)

    $numChunksToMakeFile = [Math]::Truncate($size / $chunksize)
    $outChunk = $text * $numLinesToMakeChunk

    # Creating the filename according to the size unit
    $fileName = "TestFile" + (convertSizeUnit $size) + ".txt"

    for($i=0;$i -lt $numChunksToMakeFile; $i++)
    {
    Out-File -InputObject $outChunk -encoding ASCII -filepath (Join-Path $folder $fileName) -Append
    }
    }

  • Takes four lines:

    $buffer=New-Object byte[] 4096
    $fi=[io.file]::Create('c:\temp2\testfile.txt')
    $fi.Write($buffer,0,$buffer.length)
    $fi.Close()