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 ?

    Yakov, Mar 19, 2007
    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');


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

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

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

    anno4000, Mar 19, 2007
    1. Advertisements

  3. Yakov

    Yakov Guest

    Ok thanks. This seems to be the check:

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

    Yakov, Mar 19, 2007
  4. Yakov

    anno4000 Guest

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

    anno4000, Mar 19, 2007
  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
  6. Yakov

    Ben Morrow Guest

    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';


    ~/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 Morrow, Mar 20, 2007
  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.


    anno4000, Mar 20, 2007
    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.