[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