Buffering and IO::Handle

[ Perl tips index ]
[ Subscribe to Perl tips ]

Sooner or later most Perl programmers encounter the concept of buffering on filehandles, and more often than not it's by accident. Perl's rule for buffering output is very simple: if output is sent to anything that's not a terminal, then it will be buffered by default.

Buffering is generally a good thing, by sending output to the operating system in managable chunks we reduce the amount of context switching and overheads associated with output. That makes our system more efficient and responsible, and all without any effort on behalf of the programmer.

Our problems arise when we want output to happen now, rather than when it becomes efficient to do so. Common situations include when we're writing to something that in turn is outputting to a terminal, or to a logfile where it's critical we know exactly what stage our program has reached. In these situations, we'd like to turn buffering off.

The traditional way to disable buffering on a filehandle is to use a select statement, and Perl's special $| variable:

        {
                my $old_fh = select($fh_to_unbuf);      # Select FH to unbuffer.
                $| = 1;                                 # Unbuffer that FH.
                select($old_fh);                        # Re-select the old FH.
        }

Unfortunately the code above isn't particularly clear, even with comments explaining each step. If we leave out the last step, we can accidentally change the default output for print statements, which can be a maintenance nightmare.

Luckily, there's a better way, without requiring changes to your existing code. All of Perl's filehandles act like members of the IO::Handle, whether they're contained in a scalar, or an old bareword handle like STDOUT or LOGFILE. That's right, anything you can do using IO::Handle can be done on a regular filehandle.

Now unbuffering a filehandle can be done easily and cleanly:

        use IO::Handle;
        # Unbuffer a scalar filehandle.
        $fh_to_unbuf->autoflush(1);     # Make unbuffered.
        # Unbuffer an old-style filehandle.
        *STDOUT->autoflush(1);

IO::Handle also provides a number of methods for common problems, such as explicitly flushing an output handle:

        $fh->flush();

or printing a single record in an unbuffered fashion:

        $fh->printflush("Checkpoint: Photon torpedos armed");

IO::Handle is a standard Perl module, and provides many methods that make working with filehandles simpler and more maintainable. To learn more, simply use perldoc IO::Handle.

[ Perl tips index ]
[ Subscribe to Perl tips ]


This Perl tip and associated text is copyright Perl Training Australia. You may freely distribute this text so long as it is distributed in full with this Copyright noticed attached.

If you have any questions please don't hesitate to contact us:

Email: contact@perltraining.com.au
Phone: 03 9354 6001 (Australia)
International: +61 3 9354 6001

Valid XHTML 1.0 Valid CSS