Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Determining indirect filehandles

by Masem (Monsignor)
on Jan 23, 2002 at 09:44 UTC ( #140836=snippet: print w/ replies, xml ) Need Help??

Description: You can create indirect filehandles in a number of ways, some outlined in perlfaq7, including using typeglobs and the various IO:: modules. However, checking whether a variable is a filehandle or not is not trivial; you can't use UNIVERSAL::isa since not all the types of indirects come from a common class. Instead, the following code does this check, without moving around in the file if needed. Update, seek doesn't do it as chipmunk points out, but it does appear that fileno works; normal filehandles, IO:: based ones, pipes as filehandles, all have no problem reporting a fileno. Scalars and references to anything else will trigger an error. Note that this only tells you if what you've got is a filehandle, nothing about the properties (readable, writable, etc).
my $fh = ...;  # Maybe a filehandle, maybe not...
if ( eval { fileno $fh } ) 
    { ...# Yes it is # ... }
else
    { ...# No it isn't, with $@ having details... # }
Comment on Determining indirect filehandles
Download Code
Re: Determining indirect filehandles
by chipmunk (Parson) on Jan 23, 2002 at 10:02 UTC
    Hmm, this doesn't seem to be working for me in all cases.

    When $fh is a filehandle opened on something like a pipe, on which one cannot seek, the seek fails so it seems as if $fh is not a filehandle. $! holds the reason ("Illegal seek"), and $@ is empty.

    If $fh holds a number or a string, the seek fails, but does not die, so again $! holds the reason ("Bad file number") and $@ is empty.

    If $fh holds a reference to a something other than a glob or filehandle object, the seek does die, and $@ holds "Not a GLOB reference...", as intended.

    I'm not sure how one would distinguish easily between the first two cases, other than by examining $!, which wouldn't be portable.

      Gah, you're right. I didn't test the seek solution with any pipes, and while I did test things like array refs, I didn't test it with scalars directly (mostly because in the app that I want this for, I've already removed scalars from the possible values this snippet would have gotten). However, looking around, it does look like fileno does the trick; pipes are properly recognized, but anything that's not a filehandle triggers a warning. So eval'ing that away captures non-filehandles correctly - at least, as best as I can tell. Snippet above has been updated to reflect this.

      -----------------------------------------------------
      Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      "I can see my house from here!"
      It's not what you know, but knowing how to find it if you don't know that's important

Re: Determining indirect filehandles
by ariels (Curate) on Jan 23, 2002 at 22:07 UTC

    Well, you probably want to test for defined eval { fileno $fh }...

    $fh = \*STDIN; print "Nope\n" unless eval {fileno $fh};

    It still doesn't really work, though. This must be the first example of code that doesn't work with no strict! Try this:

    $fh = 'STDOUT'; print "Nope\n" unless defined eval {fileno $fh};
    This prints <samp>Nope</samp> with strict (can't use string as symbol ref), but not without strict...

      I would think most good programmers would not have a problem with running strict at all times, but in case they don't, the latter case can be easily resolved using:
      ref( $fh ) && defined eval { fileno $fh }
      (At least, the quick spot checks that I've done indicate this works as expected for different indirect filehandle types).

      -----------------------------------------------------
      Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      "I can see my house from here!"
      It's not what you know, but knowing how to find it if you don't know that's important

Re: Determining indirect filehandles
by jmcnamara (Monsignor) on Jan 24, 2002 at 03:38 UTC

    This doesn't work for IO::Scalar filehandles however:
    #!/usr/bin/perl -w use strict; use IO::Scalar; my $str; tie *TMP, 'IO::Scalar', \$str; print TMP "Hello, World!\n"; print "Not a FH\n" unless defined eval {fileno \*TMP};
    I also tested it with IO::Socket::INET filehandles and it works for those.

    --
    John.

Back to Snippets Section

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://140836]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (8)
As of 2014-08-27 23:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (253 votes), past polls