in reply to what is filehandle's data type

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 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:

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.