checking for filehandle

Discussion in 'Perl Misc' started by Yakov, Mar 19, 2007.

  1. Yakov

    Yakov Guest

    Let's say I want to check whether $fh is a filehandle. Take 1
    is to: defined(fileno($fh)). Perfect solution ? No. When $fh is a
    tied-filehandle, $fh may not have real filedescriptor behind it
    ( for example, it sends output to the shared memory ).

    How do I check for $fh being a filehandle, the check would work
    even for tied filehandles that do not have real filedescriptor ?

    Thanks
    Yakov
     
    Yakov, Mar 19, 2007
    #1
    1. Advertisements

  2. Yakov

    anno4000 Guest

    In general it is hard to say for sure what a tied variable will respond
    to. You can use tied() to access the underlying object and make
    plausibility tests:

    my $is_fh = tied( $h) && tied( $h)->isa( 'File::Handle');

    or

    my $is_fh = tied( $h) && tied( $h)->can( 'READ');

    or similar. Both can go wrong, but will give the correct answer in most
    cases.

    In Perl 10 there will be UNIVERSAL::DOES that addresses this kind of
    problem.

    Anno
     
    anno4000, Mar 19, 2007
    #2
    1. Advertisements

  3. Yakov

    Yakov Guest

    Ok thanks. This seems to be the check:

    defined(fileno($fh)) || (tied( $fh) && tied($fh)-
    Looks ok ?

    Yakov
     
    Yakov, Mar 19, 2007
    #3
  4. Yakov

    anno4000 Guest

    Yes. In fact, testing for "TIEHANDLE" should be pretty much watertight.

    Anno
     
    anno4000, Mar 19, 2007
    #4
  5. Yakov

    Dr.Ruud Guest

    Michele Dondi schreef:
    I prefer to have it called Perl5 version 10. Perl5 will not die, Perl6
    will have her own life.

    Perl6 is a totally different language that again includes a lot of
    goodies from other tools and languages (such as Perl5), just as Perl
    originally did with awk, sed etc.
     
    Dr.Ruud, Mar 20, 2007
    #5
  6. Yakov

    Ben Morrow Guest

    Quoth -berlin.de:
    Not at all. Consider:

    #!/usr/bin/perl -l

    use Tie::Handle;
    use Tie::Scalar;
    use Scalar::Util qw/openhandle/;
    use IO::Scalar;

    {
    package Foo;

    use base qw/Tie::StdScalar Tie::StdHandle/;
    }

    sub is_a_handle {
    return 1 if defined fileno $_[0];
    return tied($_[0]) and tied($_[0])->can('TIEHANDLE');
    }

    my $x = \do { local *F };
    tie *$x, 'Tie::StdHandle';

    tie my $y, 'Foo';

    my $tmp;
    my $z = IO::Scalar->new(\$tmp);

    print '$x is ', openhandle($x) ? 'a handle' : 'not a handle';
    print '$y is ', openhandle($y) ? 'a handle' : 'not a handle';
    print '$y will appear to be ',
    is_a_handle($y) ? 'a handle' : 'not a handle';
    print '$z is ', openhandle($z) ? 'a handle' : 'not a handle';
    print '$z will appear to be ',
    is_a_handle($z) ? 'a handle' : 'not a handle';

    __END__

    ~/src/perl% perl tiehandle
    $x is a handle
    $y is not a handle
    $y will appear to be a handle
    $z is a handle
    Can't locate object method "FILENO" via package "IO::Scalar" at
    tiehandle line 15.

    The correct answer is Scalar::Util::eek:penhandle.

    Ben
     
    Ben Morrow, Mar 20, 2007
    #6
  7. Yakov

    anno4000 Guest

    [consideration of false positives snipped]

    You are right, I wasn't thinking of false positives at all.
    Thanks for pointing it out. I hadn't noticed this one, but
    Scalar::Util is full of tests that you don't use every day,
    but are hard to get right when you need them.

    blessed, isweak, isvstring, looks_like_number, openhandle,
    readonly, reftype, tainted are all more or less in that category.

    Anno

    Anno
     
    anno4000, Mar 20, 2007
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.