[Perl.sig] Perl tip: File handles and printing
Litss Coordinator
litss.coord at anu.edu.au
Wed Oct 12 10:34:09 EST 2005
==== Perl Best Practices and Understanding Regular Expressions ====
Perl Best Practices 14th - 15th November
Understanding RegExps 22nd November
Book on these courses before 21st October to receive a 30% discount off
the course costs.
http://perltraining.com.au/bookings/Melbourne.html
In the two-day course "Perl Best Practices", Damian shows practical
applications of many of his suggestions in his latest book. Get first
hand experience of how using these tips and tricks can make you a better
Perl coder. You also get a free copy of the new "Perl Best Practices"
book.
Do you use regular expressions regularly but know that there's more you
could do with them? Are you baffled when you think about how to search
for matching braces when there may be other nested pairs inside? Would
you like to know more about code embedding, user-defined assertions,
regex recursion, and backtracking control? If so, the "Understanding
Regular Expressions" course is for you.
Both courses are applicable to all levels of Perl skill, so feel free to
pass this mail onto your colleagues and co-workers who you feel may
benefit from it. If you can encourage two or more people to mention you
as their referrer, when booking between now and 21st October, we will
give you a free Perl book at the next Melbourne Perl Monger meeting.
We're happy to count your booking as one of these people.
==== File handles ====
Whenever we need to deal with reading and writing to files in Perl, we
use a file handle. In order to get a file handle for a file, we need to
open that file using ``open''. Traditionally file handles are presented
as bare words in all upper-case:
# open file for reading
open(IN, "<", $filename) or die $!;
# open file for writing
open(OUT, ">", $filename) or die $!;
# add line numbers to each line
my $line_no = 1;
while(<IN>) {
print OUT "$line_no: $_";
$line_no++;
}
Bare word file handles exist on a package basis, starting from where the
file is opened until the file is closed or the program exits. Attempting
to open another file to a file handle of the same name will close the
existing file handle before re-opening it to the new file. When this
occurs in a subroutine you call while processing your file contents you
can end up with a bug which is hard to track down. This is one example
of "action from a distance".
Fortunately, in Perl 5.6.0 and above, we can also use scalar file
handles when opening files. These file handles can be given a lexical
scope by using the ``my'' keyword, just like any other Perl scalar.
# open file for reading
open(my $input_fh, "<", $filename) or die $!;
# open file for writing
open(my $output_fh, ">", $filename) or die $!;
# copy file
my $line_no = 1;
while(<$input_fh>) {
print $output_fh "$line_no: $_";
$line_no++;
}
Scalar file handles are easily passed to subroutines or stored in data
structures. Further, when they go out of scope the file is closed. This
prevents many of the "action from a distance" problems that may occur
with the traditional file handles, and can also help reduce the number
of files needlessly left open.
== Printing to file handles ==
When printing to a file there is no comma in between the file handle and
the arguments to be printed. However adding the comma is an easy mistake
to make, and often a very hard bug to spot:
# This does not print to the OUT file handle
print OUT, $line, $sep, $_;
# This does not print to the $out file handle
print $out, $line, $sep, $_;
The lack of a comma between the file handle and the list of things to
print, allows Perl to recognise the file handle as something special.
This is called an indirect argument and is similar to the optional code
block in ``sort'', ``grep'' and ``map''. Unfortunately the comma is so
small that it can be hard for *us* to use to recognise that we've added
it. Worse still, another programmer (or ourselves in six months time)
may inadvertently insert the comma at a later date, believing the
original statement to be incorrect or "strange".
A good solution is for us to make the file handle more prominent.
Capitalised bare words provide this, but have drawbacks as mentioned
above. An excellent alternative, examined by Dr Damian Conway in his
"Perl Best Practices" book, is to add curly braces around the file
handle.
# Note we require a '*' before a bare word file handle.
print {*OUT} $line, $sep, $_;
# This makes it clear that {$out} is something special.
print {$out} $line, $sep, $_;
Just like ``sort'', ``grep'' and ``map'' we now know that if these curly
braces are followed by a comma, we've made a mistake. The braces also
make it very clear, even to a novice programmer, that ``{$out}'' is
something special, and not just another variable to be printed.
Adopting a naming convention where all file handles end in ``_fh'' can
also make it more obvious when they are being misused. $config_fh is
obviously a configuration file handle, whereas $config may not be.
==== Upcoming Courses in Canberra ====
http://perltraining.com.au/bookings/Canberra.html
Introduction to Perl: 1st - 2nd November
Intermediate Perl: 3rd - 4th November
==== Upcoming Courses in Melbourne ====
http://perltraining.com.au/bookings/Melbourne.html
Perl Best Practices: 14th - 15th November
Understanding Regular Expressions: 22nd November
Web Development with Perl: 1st - 2nd December
==== Upcoming Courses in Sydney ====
http://perltraining.com.au/bookings/Sydney.html
Web Development with Perl: 28th - 29th November
____________________________________________________________________________
CONTACT INFORMATION for Information Infrastructure Services
LITSS Home Page: http://its.anu.edu.au/litss/
General Enquiries: extn 54378 or litss.coord at anu.edu.au
Software Enquiries: extn 55035 or software at anu.edu.au
Fault Reporting: extn 59666 or doi.helpdesk at anu.edu.au
Facsimile: 6125 0449
After Hours:
Major Communication Network Faults Only: ANU Security 612 52249
____________________________________________________________________________
--
More information about the Perl.sig
mailing list