Perl Basics: Reading, Writing and Taking a Bite
By Lisa Hui

Sematics of Opening a File

Opening a file for reading and writing looks very similar. Unlike C++, you can reuse the same filehandle to read and write to a file (as long as they are not used simultaneously). Let's say we want to call our filehandle READFILE (how original! Well, you can use other words but this one is just so that it is easier to tell what you're doing with this filehandle).

open(READFILE, "file.txt");

There, you just opened a file to read but haven't done anything with it yet :) To close it, just mention the filehandle:

close(READFILE);

Don't forget to close your files after you're finished! Let's say our file.txt contains the following information:

Bob owes me $50.
I owe Laura $25.
Jeannie just wants to mooch $5 from everyone.
We're a happy family.

What would we want to do with that? Let's just take the information from the text file and print it out to the browser.

open(SESAME,"file.txt");
  @filecontents = <SESAME>;
close(SESAME);

In those three lines above, we've just opened the file, dumped (copied) the contents of the file to an array called "filecontents" and closed the file. Now we have the stuff from file.txt stored line by line in @filecontents. How are the file.txt contents stored in @filecontents? It is the equivalent of:

$filecontents[0] = "Bob owes me $50.";
$filecontents[1] = "I owe Laura $25.";
$filecontents[2] = "Jeannie just wants to mooch $5 from everyone.";
$filecontents[3] = "We're a happy family.";

So to print it to the browser, we whip out our trusty foreach loop:

print "Content-type: text/html\n\n";
foreach $line(@filecontents) { print "$line"; }

And we've accomplished the task :) What about writing and stuff like that? Like I mentioned above, the initiation process is similar.

To open a new file (where FILEHANDLE is a filehandle we want to use), we write (>):

open(FILEHANDLE,">file.txt");
   foreach $line(@filecontents) { print FILEHANDLE "$line"; }
close(FILEHANDLE);

What did we just do? We just opened a new file called "file.txt" but if file.txt already existed, this one will write over it (all the old info is deleted automatically). Notice the one angle bracket (>) pointing at the filename - that's telling the open operator to open a new file for writing. For reading we could omit the angle bracket (or explicitly add a < angle bracket) and it would just let you read the contents of the file but not write to it. When you open a filehandle for reading, the information is immediately copied over to the filehandle you specified, and that is where you grab the info.

Notice that I specified the filehandle in the print function. This tells the print function to write $line into the file and not output it to the browser. (Actually, if you don't specify a filehandle for print, it will assume the default filehandle for output - see Perl Basics: Becoming a Perl Newbie Extraordinaire)

Perl also allows an append file command (>>):

open(FILEHANDLE,">>file.txt");
   foreach $line(@filecontents) { print FILEHANDLE "$line"; }
close(FILEHANDLE);

This will open file.txt and leave everything that's already in there intact, but add (attach at the end) the contents of @filecontents.

Chop and Chomp

Not just used in reference to food, these two operators will remove the last character in a string variable. Chop will indiscriminately remove the last character whereas Chomp will only remove a newline character (\n). I find that I use it most when working with files (hence the reason why I'm mentioning it here). When we were working with file.txt, there was more than one line. When you hit 'Enter' or 'Return' on your keyboard, it creates a newline:

Bob owes me $50.\n
I owe Laura $25.\n
Jeannie just wants to mooch $5 from everyone.\n
We're a happy family.

Notice that there is no newline after the last sentence. If you were going to append something to this file, it would not automatically add a newline first, it would add the data on the same line as "We're a happy family." Thus this would screw up copying over files and appending lines. To avoid this, you could use chomp to remove the newline and then when writing over the old file, use print "$line\n"; instead of print "$line"; (If you had just used print "$line\n"; without chomping first, you would've ended up with 2 newlines for the $line's that already had a newline.) Sure you could just put in that last newline, but in case you omit it, this could prevent a lot of potential display errors.

open(FILEHANDLE,">file.txt");
   foreach $line(@filecontents) {
      chomp($line);
      print FILEHANDLE "$line\n";
   }
close(FILEHANDLE);

Chop has similar "perl grammer" [chop($line);] to that of chomp but I prefer to chomp in most cases that require something like this :)

Require

Require works somewhat like an include statement in C++ does, except that this function executes the code found in the file specified. [Example: require 'file.pl'; ] The function checks to make sure that this file specified in the quotes were not already included in the file (preventing duplicates). It must return true as the last value in the file to indicate that the code within has been successfully executed, so when you separate some code (whether it be just definitions for variables or subroutines) by putting it in a your required file, make the last line:

1;

...to be sure that it will return true. Often this is used in perl scripts to create separate configuration files so that the main script can just include this when it is executed and the person installing the script doesn't have to even look at the code itself, just set a few variables.