perlfan99 has asked for the wisdom of the Perl Monks concerning the following question:

dear monks,

in perl, data types are scalar, array, hash, code, reference. so what is the data type for a file handle? is it an integer wrapper? internally it uses c function which represents file handle as an integer.

i have seen some code like:
open(FH, "> $log"); function(\*FH);
what does \*FH means? a pointer to a file handle( a pointer to an integer)?

thanks!

Replies are listed 'Best First'.
Re: what is filehandle's data type
by GrandFather (Saint) on Aug 20, 2008 at 04:04 UTC

    It's a GLOB:

    use strict; use warnings; my $str; open my $fileHandle, '>', \$str; print ref $fileHandle;

    Prints:

    GLOB

    \*FH passes a reference to a GLOB to function.


    Perl reduces RSI - it saves typing
Re: what is filehandle's data type
by jwkrahn (Abbot) on Aug 20, 2008 at 04:11 UTC
Re: what is filehandle's data type
by Anonymous Monk on Aug 20, 2008 at 04:09 UTC
    so what is the data type for a file handle? is it an integer wrapper?
    Wouldn't you know it, docs :) Typeglobs and Filehandles
Re: what is filehandle's data type
by gone2015 (Deacon) on Aug 20, 2008 at 20:16 UTC

    It's a good question.

    You can get to the underlying integer using fileno(), but that doesn't answer the question of what a file handle is in Perl -- which turns out to be trickier than it looks...

    We all know that an identifier in Perl can refer to a SCALAR, an ARRAY, a HASH or a subroutine (CODE) -- and the prefixes $, @, % and & specify which. An identifier can also refer to a file handle (IO) or a FORMAT. An identifier without a prefix generally refers to a subroutine, but in some special contexts it refers to a file handle or a FORMAT.

    The unfortunate consequence is that you cannot pass a file handle identifier to a subroutine or store it, because in those contexts an identifier with no prefix is treated as a subroutine.

    Now, the collection of all possible values that a name can refer to is known as a GLOB, and the prefix * is used to specify that. You can pass a GLOB and you can store one -- so my $a = *SUE ; makes $a an implicit reference to the GLOB named SUE. You can also pass a reference to a GLOB and store one -- thus my $b = \*SUE ; stores an explicit reference to the GLOB named SUE in $b. The construct *SUE{SCALAR} returns a reference to the SCALAR part of the GLOB named SUE. (The significance of all this may become clear later.) So that:

    use strict ; use warnings ; *SUE = \127 ; my $a = *SUE ; my $b = \*SUE ; printf "sex(\$a) = %10s and \${\*{\$a}{SCALAR}} = %d\n", sex($a), ${ +*{$a}{SCALAR}} ; printf "sex(\$b) = %10s and \${\*{\$b}{SCALAR}} = %d\n", sex($b), ${ +*{$b}{SCALAR}} ; sub sex { my ($thing) = @_ ; my $sex = ref($thing) ; return $sex ? "ref:$sex" : ref(\$thing) ; } ;

    prints:

    sex($a) = GLOB and ${*{$a}{SCALAR}} = 127 sex($b) = ref:GLOB and ${*{$b}{SCALAR}} = 127

    so... although $a and $b are not the same as far as ref is concerned, they can both be used as references to the GLOB (just in case we'd forgotten this is Perl).

    So a file handle is the IO part of a GLOB. However, where Perl expects a file handle, it will accept a number of things:

    • the GLOB which has the required IO part
    • a reference to that GLOB
    • a FileHandle object (whose underlying type is a GLOB which has the required IO part)
    • an IO::Handle object (whose underlying type is a GLOB which has the required IO part)
    The following illustrates this:

    use strict ; use warnings ; use IO::Handle ; use FileHandle ; use Scalar::Util qw(reftype) ; print "1________________________________\n", 'open FH, ">&2" ;', "\n" ; open FH, ">&2" ; show('*FH', *FH) ; show('\*FH', \*FH) ; show('*FH{IO}', *FH{IO}) ; print "\n", "2________________________________\n", 'open my $OUT, ">&2" ; ', "\n" ; open my $OUT, ">&2" ; show('$OUT', $OUT) ; show('*$OUT{IO}', *$OUT{IO}) ; print "\n", "3________________________________\n", 'my $ih = new IO::Handle ;', "\n" ; my $ih = new IO::Handle ; print 'reftype($ih) = ', reftype($ih), "\n" ; print 'open $ih, ">&2" ;', "\n" ; open $ih, ">&2" ; show('$ih', $ih) ; show('*$ih{IO}', *$ih{IO}) ; print "\n", "4________________________________\n", 'my $fh = new FileHandle ;', "\n" ; my $fh = new FileHandle ; print 'reftype($fh) = ', reftype($fh), "\n" ; print 'open $fh, ">&2" ;', "\n" ; open $fh, ">&2" ; show('$fh', $fh) ; show('*$fh{IO}', *$fh{IO}) ; sub show { my ($tag, $FH) = @_ ; my $can = $FH->can('autoflush') ? "can 'autoflush'" : "can NOT 'au +toflush'" ; my $tst = defined(-t $FH) ? "OK" : 'undef' ; printf $FH " show%-12s => %-18s fileno=%d test=%-5s %s\n", "($tag)", sex($FH), fileno($FH), $tst, $can ; } ; sub sex { my ($thing) = @_ ; my $sex = ref($thing) ; return $sex ? "ref:$sex" : ref(\$thing) ; } ;

    prints:

    1________________________________ open FH, ">&2" ; show(*FH) => GLOB fileno=4 test=OK can N +OT 'autoflush' show(\*FH) => ref:GLOB fileno=4 test=OK can N +OT 'autoflush' show(*FH{IO}) => ref:FileHandle fileno=4 test=undef can ' +autoflush' 2________________________________ open my $OUT, ">&2" ; show($OUT) => ref:GLOB fileno=5 test=OK can N +OT 'autoflush' show(*$OUT{IO}) => ref:FileHandle fileno=5 test=undef can ' +autoflush' 3________________________________ my $ih = new IO::Handle ; reftype($ih) = GLOB open $ih, ">&2" ; show($ih) => ref:IO::Handle fileno=6 test=OK can ' +autoflush' show(*$ih{IO}) => ref:FileHandle fileno=6 test=undef can ' +autoflush' 4________________________________ my $fh = new FileHandle ; reftype($fh) = GLOB open $fh, ">&2" ; show($fh) => ref:FileHandle fileno=7 test=OK can ' +autoflush' show(*$fh{IO}) => ref:FileHandle fileno=7 test=undef can ' +autoflush'

    This shows:

    1. The "traditional" file handle, which can be passed or stored as an implied GLOB reference (*FH) or an explicit GLOB reference (\*FH).
    2. This form of open sets $OUT to be a reference to an anonymous GLOB whose IO part is set -- this is known as an indirect file handle. $OUT can be used everywhere where Perl expects a FILEHANDLE.
    3. An IO::Handle object is created, which can then be used where a FILEHANDLE is required. Note that the underlying type of the object is a GLOB.
    4. A FileHandle object is created, which can then be used where a FILEHANDLE is required. Note that the underlying type of the object is a GLOB.

    This also shows:

    • All the things that act as file handles are implicit or explicit references to a GLOB with a suitable IO part, or objects whose underlying type is such a GLOB (or references to an IO value).
    • The IO part of a GLOB with a file handle is blessed as a FileHandle
    • The file test operators require an implicit or explicit reference to a GLOB with a suitable IO part or an object whose underlying type is such a GLOB. These operators do not work on reference to IO values -- unlike print etc. (If it wasn't quirky, it wouldn't be Perl.)

    So... what was the question, again ?

    A thing which acts as a FILEHANDLE can have a number of apparently different data types.

    I would recommend using $FH "indirect" file handles or IO:Handle objects, which can be passed around or stored in data structures as straightforward scalars. This can be achieved by:

    open my $FH, ..... ;

    or:

    use IO::Handle ; open my $FH = new IO::Handle, .... ;

    depending on whether you want the IO:Handle collection of methods to be applicable.


    "But what about the special file handles like STDERR and DATA ?", I hear you cry...

    The trick here is:

    $STDERR = \*STDERR ; my $DATA = \*DATA ;

    or, if you want the IO::Handle methods:

    $STDERR = bless \*STDERR, 'IO::Handle' ; my $DATA = bless \*DATA, 'IO::Handle' ;

    Noting that the names STDIN, STDOUT and STDERR are special, and refer to main:: variables wherever they are used and are implicitly declared (so no our or my required.)


    From deep in Perl's past it is possible to use a scalar string value as a reference to a file handle. Consider:

    no strict ; announce(STDERR, "Hello World\n") ; sub announce { my $FH = shift ; print $FH @_ ; } ;

    Which looks as though it works by passing the file handle STDERR to the subroutine announce. In fact, what is happening is that (a) the bareword STDERR is passed as a string, and (b) the print treats the contents of $FH as the name of the FILEHANDLE to use (ie as a symbolic reference).

    One assumes that in the dim and distant past, this looked like a particularly cunning plan to deal with the problem of passing file handles.

    Of course, in modern times use strict ; will whinge like mad about both the bareword and the sybolic reference.