CIT 042 Index > Files

Files

Up to now, all your input has been from the keyboard and all your output has been to the screen. When you want to read from or write to a file on disk, you need to create a file handle. File handles don’t have a prefix like $, @, or %; they are just plain identifiers. By convention, file handle names are written in all uppercase. One of the file handles that is built into Perl is called STDIN, which means “standard input,” and you have been using it all along to read from the keyboard.

Opening a File

You use the open() function to open a file. The open() function takes three parameters:

  1. The name of a file handle
  2. A mode string that tells whether you are opening the file for reading or writing
  3. The file path name

The function returns true if successful and undef if unsuccessful.

Reading a File

To open a file for reading, you use '<' as the mode string. Here is code that will open a file named mydata.txt, read it, and print it with line numbers:

my $result;
my $data;
my $line = 1;
$result = open(INFILE, '<', 'mydata.txt');
if ($result)
{
  while ($data = <INFILE>)
  {
    print "$line\t$data";
    $line++;
  }
  close(INFILE);
}
else
{
  print("Cannot open input file: $!\n");
}

The $! in the last print statement gives the error message returned by the operating system.

Writing a File

To open a file for writing, you use '>' as the mode string. Here is code that will open a file named squares.txt and write the squares of the numbers 0 through 10 to that file.

my $result;
my $squared;

$result = open(OUTFILE, '>', 'squares.txt');
if ($result)
{
  for (my $i = 0; $i < 11; $i++)
  {
    $squared = $i ** 2;
    print OUTFILE "$i: $squared\n";
  }
  close(OUTFILE);
}
else
{
  print("Cannot open output file: $!\n");
}

When you open a file for writing, if the file does not already exist, Perl creates it. If it does already exist, Perl will overwrite the file. To try this, create a file named squares.txt and fill it with some text you don’t care about. Then run the preceding program.

Specifying File Names

Perl is from the world of Linux, where / is the separator for elements of a path name. In Windows, you use a \ (backslash). Perl will accept both. If you want to open a file C:\temp\mydata.txt, you may use any of the following.

$result = open(INFILE, '<', 'C:/temp/mydata.txt');
$result = open(INFILE, '<', 'C:\temp\mydata.txt');
$result = open(INFILE, '<', "C:\\temp\\mydata.txt");

File Tests

What if you want to accept a file name from a user, and wish to be sure that the file exists before you read it or, more important, overwrite it? Perl has a way to test if a file exists or not. Here’s a program that will ask for an input file name and an output file name. If the input file name doesn’t exist, or if the output file does already exist, the program won’t do anything. Otherwise, it will read the input file and copy it, with line numbers, to the output file.

Notice that I check to see if I can open the file successfully even if the file exists (or doesn’t). I need to do this in case I don’t have permission to read the file or write a new file in the directory that I named.

Command Line Arguments

You might want to get your file names from the command line rather than prompting the user for them (this is the “Unix way” of doing things). The command line arguments are stored in a special array named @ARGV. The name of the program currently running is stored in the $0 (that’s a zero, not a capital letter “oh”). Here’s a program that calculates the area of a rectangle when given the width and height as its two arguments. Notice that it gives an appropriate error message if you give it too few or too many command line arguments.

#!/usr/bin/perl
use strict;

my $width;
my $height;
my $area;

if (@ARGV == 2)
{
  ($width, $height) = @ARGV;
  $area = $width * $height;
  print("The area is $area square units.\n");
}
else
{
  print("Usage: $0 width height");
}