Go4Expert

Go4Expert (http://www.go4expert.com/)
-   Perl (http://www.go4expert.com/articles/perl-tutorials/)
-   -   Some Tricks With Filehandles in Perl (http://www.go4expert.com/articles/tricks-filehandles-perl-t10858/)

pradeep 28May2008 07:35

Some Tricks With Filehandles in Perl
 

Read An Entire File All At Once



At times we need to read the contents of a file all at once, instead of reading line by line, or reading the contents line-wise into an array, here's how we can read the contents of a file into a scalar as text.

Code: Perl

open FILE, '</tmp/page.html' or die $!;
  flock FILE, 1 or die $!; # wait for lock
  seek(FILE, 0, 0); # move pointer to beginning
  my $slurp = do{local $/; <FILE>}; # slurp ;-)
  close(FILE); # close file, automatically releases the lock
 
  print $slurp;


If you're sure you really want to fill your computer's operating memory with the contents of a file, then this trick will accomplish that. The angle brackets "<>" work on a file handle by returning either: the next record, in a scalar context or a list of all the records, in an array context. It would be wise to format your data into manageable records, separated by some token characters. The special Perl variable $/ can be set to that record separator. By default $/ will be a newline, but by undefining it you cause perl to consider the entire file to be one single record. Because $/ is a global variable changing it in one place will have side-effects elsewhere. For that reason we create a limited scope and localize our $/ redefinition inside it by wrapping the work in a do{...} block. Note also that we lock the file for reading, which will wait for any other flocks to release before we try to access it.

Doing The Same In A Better Manner



The above example looks ugly, so we install the IO::All module and things become much cleaner. The IO::All module brings together several powerful IO modules and offers a single unified interface to all of them.

Code: Perl

use IO::All;
 
  my $file = io("./anthem.txt")->lock;
  my $slurp = $file->slurp;
  $file->close;
 
  print $slurp;


Assign One Filehandle To Another



Code: Perl

open(MYOUT, "> log.log");
  *STDOUT = *MYOUT;
 
  print "message";


(text file "log.log" now contains string "message")

You probably have used perl's print function with a filehandle before, but did you know that even if you don't use a filehandle perl assumes you mean a default one called "STDOUT"? C programmers will recognize that as the standard output -- usually the screen, or terminal window (or the browser, when writing CGIs). What we've done here is create our own filehandle, pointing to a file. Then we've done something a little sneaky -- we've used the star symbol-prefix to refer to STDOUT as a typeglob. Typeglobs allow use to create an "alias" of sorts, making all variables of a certain name point to another variable of a certain name. The second line of this snippet basically says that the STDOUT variable now aliases to the MYOUT variable. Once this is done any prints to the default filehandle go instead to our own filehandle.

Writing To Two Filehandles At The Same Time



If, for whatever reason you wanted to print the same string to two places at once you are trying to do what the Unix utility "tee" does. This functionality is available in your perl script even if you aren't running it on Unix, via the IO::Tee module. Tee is object-oriented so you must first create a Tee object using the new constructor. This sub takes two arguments, each can be either a string representing a filehandle or a reference to an open filehandle. In this case we use a string representing an appending filehandle, pointing to a file called "debuglog.txt" and a built-in filehandle called STDOUT. This built-in filehandle is automatically created and it is in fact the default target that print points to (usually the terminal or, for a CGI the browser). To get a reference to a filehandle requires that we use the back-slash operator on a typeglob symbol, the star. Typeglobs are a special way to refer to all variables of a given name at once (regardless of its "type", array, hash, scalar etc.). Its necessary to use the star because filehandles have no prefix symbol of their own. new returns an instance object of the class Tee, and we assign this to the scalar $tee. Now whenever we print to the $tee object we are actually sending the string to two places at once! Cool, isn't it?

Code: Perl

use IO::Tee;
 
  $tee = IO::Tee->new(">> debug.log", \*STDOUT);
 
  print $tee "an error occurred on ".scalar(localtime)."\n";



File Contents
Code:

  an error occurred on Fri May 27 07:44:20 2008

shabbir 2Jun2008 16:28

Re: Some Tricks With Filehandles in Perl
 
Nomination for article of the month of May

shabbir 18Jun2008 21:44

Re: Some Tricks With Filehandles in Perl
 
Quote:

Originally Posted by shabbir

Start Voting now

Karapaz 7Jun2009 15:08

Some Tricks With Filehandles in Perl
 
Ive got Cygwin Perl 5.10.0 experimental installed, not the XAMPP perl add-on.My CGI was failing because it couldnt find any of the perl libs. The apache error log said things like:Code:


All times are GMT +5.5. The time now is 09:11.