Reading/writing files

Overview

I can’t remember why now, but recently I had reason to do some file input/output using PowerShell. I guess there are different ways of achieving this, but chose to practice using .NET from PowerShell. 

The following code simply reads an input file and writes the data out to an output file. No other processing is involved.

I started off with four variables.

  • $inrec – a string variable used to receive data from the input file and write to the output file.
  • $counter – an integer to count the lines processed.
  • $infile – a string variable representing the absolute path of the input file.
  • $outfile – a string variable representing the absolute path of the output file.

Input

From this, I created my input file object.

$input = New-Object -TypeName System.IO.StreamReader($infile);

The StreamReader Class constructor is overridden 11 times but the version I used was simply:

public StreamReader(string path)

which initializes a new instance of the StreamReader class for the specified file name supplied, i.e., variable $infile.

Output

The other side of the coin is the StreamWriter Class. Because I chose to use the constructor:

public StreamWriter(Stream, Encoding)

I had to create a stream object for the first parameter. This was done via:

public FileStream(path, FileMode, FileAccess)

The documentation for Constructor (String, FileMode, FileAccess), tells us these parameters are:

  1. path – A relative or absolute path for the file. In our example, variable $outfile.
  2. FileMode – How to open the file. It could be that you want to append to an existing file or create a new one. With the code I’ve used, I’m creating a new file each time round, thus overwriting the file if it exists.
  3. FileAccess – How we’re going to access the file, i.e., read, write or read and write to the file. I’ve chosen to just write to the file.

This was achieved with the code:

$outStream = New-Object -TypeName System.IO.FileStream(
 $outfile,
 [System.IO.FileMode]::Create,
 [System.IO.FileAccess]::Write);

Types System.IO.FileMode and System.IO.FileAccess are enumerated objects in which the documentation will tell you the members of these objects. Another way of finding out the members is to run the following statements at the PowerShell prompt:

PS> [Enum]::GetNames( [System.IO.FileMode] )
PS> [Enum]::GetNames( [System.IO.FileAccess] )

Now we’ve created the output stream, we can create the StreamWriter object with:

$output = New-Object -TypeName System.IO.StreamWriter(
 $outStream,
 [System.Text.Encoding]::ASCII);

In other words we’ve created a FileStream object in order to create a StreamWriterobject.

I’ve used a WHILE loop to read from the input file.

$inrec = $input.ReadLine();
while ($inrec -ne $null) {
$output.WriteLine($inrec);
$counter++;

$inrec = $input.ReadLine();
}

The StreamReader.ReadLine Method $input.ReadLine() reads the next line from the input stream, or null if the end of the input stream is reached.

To tidy up at the end of the file, I’ve done:


$input.Close();
$input.Dispose();
$output.Flush();
$output.Close();
$output.Dispose();

For good measure, I’ve used the System.IO.FileInfo object to see what the length of the output file is in bytes.

$filelen = New-Object -TypeName System.IO.FileInfo($outfile);
Write-Host "File $($outfile.ToString()) has length $($filelen.length) bytes";

I always forget where I’ve my files are, so I use the following to remind me:

Write-Host "Lines written: $counter";
Write-Host "Files used:";
Write-Host ("Input file: {0}`nOutput file: {1}" -f $infile, $outfile);
cat $outfile | Measure-Object -Line;
Write-Host "All done now";

Summary

Putting all this together gives us:


$inrec="";
$counter=0;
$infile="C:\junk\gashinputfile.txt";
$outfile="C:\junk\gashoutputfile.txt";

$input = New-Object -TypeName System.IO.StreamReader($infile);
$outStream = New-Object -TypeName System.IO.FileStream(
 $outfile,
 [System.IO.FileMode]::Create,
 [System.IO.FileAccess]::Write);
$output = New-Object -TypeName System.IO.StreamWriter(
 $outStream,
 [System.Text.Encoding]::ASCII);

$inrec = $input.ReadLine();
while ($inrec -ne $null) {
 $output.WriteLine($inrec);
 $counter++;

$inrec = $input.ReadLine();
}

$input.Close();
$input.Dispose();
$output.Flush();
$output.Close();
$output.Dispose();

$filelen = New-Object -TypeName System.IO.FileInfo($outfile);
Write-Host "File $($outfile.ToString()) has length $($filelen.length) bytes";

Write-Host "Lines written: $counter";
Write-Host "Files used:";
Write-Host ("Input file: {0}`nOutput file: {1}" -f $infile, $outfile);
cat $outfile | Measure-Object -Line;
Write-Host "All done now";

What you won’t see in this program is any error handling. As this was a learning exercise, I can come back to this subject at a later date.

See also

StreamReader Class

FileStream Class

StreamWriter Class

Advertisements
This entry was posted in powershell and tagged , . Bookmark the permalink.

One Response to Reading/writing files

  1. Anton says:

    Hi, thanks a lot for the script and the accompanying comments and explanations, as a beginner this was i big help. I occasionally need to manipulate massive text files in excess of 120Gb (dont ask…) and your script worked very well, i needed to tweak it a bit to suit my purpose.

    thanks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s