CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Frequently Asked Questions:
How can I use a filehandle indirectly?

 



Jasmine
Administrator

Jan 26, 2001, 10:12 AM

Post #1 of 1 (1748 views)
How can I use a filehandle indirectly? Can't Post

(From the Perl FAQ)

How can I use a filehandle indirectly?

An indirect filehandle is using something other than a symbol in a place that a filehandle is expected. Here are ways to get those:

Code
    $fh =   SOME_FH;       # bareword is strict-subs hostile 
$fh = "SOME_FH"; # strict-refs hostile; same package only
$fh = *SOME_FH; # typeglob
$fh = \*SOME_FH; # ref to typeglob (bless-able)
$fh = *SOME_FH{IO}; # blessed IO::Handle from *SOME_FH typeglob

Or to use the new method from the FileHandle or IO modules to create an anonymous filehandle, store that in a scalar variable, and use it as though it were a normal filehandle.

Code
    use FileHandle; 
$fh = FileHandle->new();

use IO::Handle; # 5.004 or higher
$fh = IO::Handle->new();

Then use any of those as you would a normal filehandle. Anywhere that Perl is expecting a filehandle, an indirect filehandle may be used instead. An indirect filehandle is just a scalar variable that contains a filehandle. Functions like print, open, seek, or the functions or the <FH> diamond operator will accept either a read filehandle or a scalar variable containing one:

Code
    ($ifh, $ofh, $efh) = (*STDIN, *STDOUT, *STDERR); 
print $ofh "Type it: ";
$got = <$ifh>
print $efh "What was that: $got";

Of you're passing a filehandle to a function, you can write the function in two ways:

Code
    sub accept_fh { 
my $fh = shift;
print $fh "Sending to indirect filehandle\n";
}

Or it can localize a typeglob and use the filehandle directly:

Code
    sub accept_fh { 
local *FH = shift;
print FH "Sending to localized filehandle\n";
}

Both styles work with either objects or typeglobs of real filehandles. (They might also work with strings under some circumstances, but this is risky.)

Code
    accept_fh(*STDOUT); 
accept_fh($handle);

In the examples above, we assigned the filehandle to a scalar variable before using it. That is because only simple scalar variables, not expressions or subscripts into hashes or arrays, can be used with built-ins like print, printf, or the diamond operator. These are illegal and won't even compile:

Code
    @fd = (*STDIN, *STDOUT, *STDERR); 
print $fd[1] "Type it: "; # WRONG
$got = <$fd[0]> # WRONG
print $fd[2] "What was that: $got"; # WRONG

With print and printf, you get around this by using a block and an expression where you would place the filehandle:

Code
    print  { $fd[1] } "funny stuff\n"; 
printf { $fd[1] } "Pity the poor %x.\n", 3_735_928_559;
# Pity the poor deadbeef.

That block is a proper block like any other, so you can put more complicated code there. This sends the message out to one of two places:

Code
    $ok = -x "/bin/cat";                 
print { $ok ? $fd[1] : $fd[2] } "cat stat $ok\n";
print { $fd[ 1+ ($ok || 0) ] } "cat stat $ok\n";

This approach of treating print and printf like object methods calls doesn't work for the diamond operator. That's because it's a real operator, not just a function with a comma-less argument. Assuming you've been storing typeglobs in your structure as we did above, you can use the built-in function named readline to reads a record just as <> does. Given the initialization shown above for @fd, this would work, but only because readline() require a typeglob. It doesn't work with objects or strings, which might be a bug we haven't fixed yet.

Code
    $got = readline($fd[0]);

Let it be noted that the flakiness of indirect filehandles is not related to whether they're strings, typeglobs, objects, or anything else. It's the syntax of the fundamental operators. Playing the object game doesn't help you at all here.



 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives