Streams

As far as Unix and Windows are concerned, a file is nothing more than a sequence of characters. The MacIntosh operating system, on the other hand, attaches additional information (in the so-called resource fork) such as the type of the file, the program that created it, etc. In both cases though, programs deal with the file in a similar way, which can be understood by looking at a related problem. Suppose that you want to ask your friend for the solutions to a CPSC 219 lab (of course, we know you would never do that). Before talking to your friend, you must first pick up the phone and dial the appropriate phone number. Once you are connected, then you can start chatting.

Similarly, before a program can access the data contained in a file, it must setup an object (the phone) that will act as an intermediary between the file (your friend) and your program (you). This is called opening the file, and the object that allows your program to access the data in the file is called a stream, or handle.

Thus, a program, whether it is written in C++, Perl, Java, Pascal, or pretty much any other language, accesses a file using the following three step process:

The C++ library provides two basic classes for operations on streams: istream (for input, where we read the data from the file), and ostream (for output, where we write data to the file). For instance, cin is an object of type istream, while cout is an object of type ostream. Similar types of objects exist in most programming languages: the FILE structure in C, the InputStream and OutputStream classes in Java, the File type in Pascal, etc.

Filehandles

In Perl, a stream is represented by a filehandle. A filehandle can refer to a file, pipe, socket or device, but it is used in the same way in all cases. Here is how you would create a filehandle that reads from an existing file (where SESAME is the name of the filehandle):

open(SESAME, "filename");

It is customary to pick an uppercase name for a filehandle. Once you have opened a file for input, you can read lines from the file using the line reading (angle) operator <>. Simply place the filehandle (or STDIN if you want to use standard input) between the angle brackets. For example, the following program will prompt you for your name, and then greet you:

print STDOUT "What is your name?\n";
$name = <STDIN>;
print STDOUT "Hello ";
print STDOUT $name;

We now know how to open files for input, but what about opening files for output, or appending output to the end of already existing files? These tasks are easy to accomplish in Perl, as it suffices to insert the appropriate character(s) at the beginning of the file name. To open files for output, and appending, we simply insert the symbols >, and >> respectively. For example:

open(INFILE, $file);          # Open $file for input
open(INFILE, "<$file");       # Also open $file for input
open(OUTFILE, ">$file");      # Open $file for output
open(APPENDFILE, ">>$file");  # Open $file for appending

Once we have opened a file for output, we write to the file using a print statement. To accomplish this task, the print statement takes two arguments: a file descriptor and the string to be written to the file. Here is an example:

print OUTFILE "This line will be written to the file.\n";

If the first argument is omitted, then the string is printed onto the standard output. Of course, once you have finished working with a file that has been opened, you should close the file.  In Perl, this is accomplished with the "close()" function.  The "close()" function takes a filehandle as an argument, for example:

close(INFILE);    # Close INFILE

The following example ties everything together. Although the actual processing performed on the file is minimal, the example illustrates the basics of opening and closing files for both input and output.

open(S_OUT, '>-');                    # Open stdout and
print S_OUT "Starting Execution...";  # Write a message

$file = '/etc/shells'
open(INFILE, "<$file");               # Open /etc/shells to read input

$file = "copy_shells.txt";
open(OUTFILE, ">$file");              # Open 'copy_shells.txt' for output

@lines = <INFILE>;                    # Read in the '/etc/shells' file and
print OUTFILE @lines;                 # Write a copy of it to the output file

close(INFILE);                        # Close both input and
close(OUTFILE);                       # Output files

print S_OUT "DONE!\n";                # Write a 'done' message and
close(S_OUT);                         # Close stdout

Perl filehandles make opening and processing files clean and very easy. Most of the unpleasantness associated with processing text files in C++ has been hidden by Perl.