start page | rating of books | rating of authors | reviews | copyrights

Book HomeLearning Perl, 3rd EditionSearch this book

11.4. Using Filehandles

Once a filehandle is open for reading, you can read lines from it just like you can read from standard input with STDIN. So, for example, to read lines from the Unix password file:

open PASSWD, "/etc/passwd"
  or die "How did you get logged in? ($!)";

while (<PASSWD>) {
  chomp;
  if (/^root:/) {  # found root entry...
    ...;
  }
}

In this example, the die message uses parentheses around $!. Those are merely parentheses around the message in the output. (Sometimes a punctuation mark is just a punctuation mark.) As you can see, what we've been calling the "line-input operator" is really made of two components; the angle brackets (the real line-input operator) are around an input filehandle. Each line of input is then tested to see if it begins with root followed by a colon, triggering unseen actions.

A filehandle open for writing or appending may be used with print or printf, appearing immediately after the keyword but before the list of arguments:

print LOG "Captain's log, stardate 3.14159\n";  # output goes to LOG
printf STDERR "%d percent complete.\n", $done/$total * 100;

Did you notice that there's no comma between the filehandle and the items to be printed?[259] This looks especially weird if you use parentheses. Either of these forms is correct:

[259]If you got straight A's in freshman English or Linguistics, when we say that this is called "indirect object syntax," you may say "Ah, of course! I see why there's no comma after the filehandle name -- it's an indirect object!" We didn't get straight A's; we don't understand why there's no comma; we merely omit it because Larry told us that we should omit the comma.

printf (STDERR "%d percent complete.\n", $done/$total * 100);
printf STDERR ("%d percent complete.\n", $done/$total * 100);

11.4.1. Changing the Default Output Filehandle

By default, if you don't give a filehandle to print (or to printf, as everything we say here about one applies equally well to the other), the output will go to STDOUT. But that default may be changed with the select operator. Here we'll send some output lines to BEDROCK:

select BEDROCK;
print "I hope Mr. Slate doesn't find out about this.\n";
print "Wilma!\n";

Once you've selected a filehandle as the default for output, it will stay that way. But it's generally a bad idea to confuse the rest of the program, so you should generally set it back to STDOUT when you're done.[260]

[260]In the unlikely case that STDOUT might not be the selected filehandle, you could save and restore the filehandle, using the technique shown in the documentation for select in the perlfunc manpage. And as long as we're sending you to that manpage, we may as well tell you that there are actually two builtin functions in Perl named select, and both covered in the perlfunc manpage. The other select always has four arguments, so it's sometimes called "four-argument select".

Also by default, the output to each filehandle is buffered. Setting the special $| variable to 1 will set the currently selected filehandle (that is, the one selected at the time that the variable is modified) to always flush the buffer after each output operation. So if you wanted to be sure that the logfile gets its entries at once, in case you might be reading the log to monitor progress of your long-running program, you could use something like this:

select LOG;
$| = 1;  # don't keep LOG entries sitting in the buffer
select STDOUT;
# ... time passes, babies learn to walk, tectonic plates shift, and then...
print LOG "This gets written to the LOG at once!\n";


Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.