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

After spending what felt like a long time browsing through the documentation and so on I think I figured this out on my own, but now the time has come to ask for some enlightenment...

I am trying to write a subroutine that will accept either a filename to be opened and read from, or an already opened filehandle to just read from. My problem at first seemed to be that I had a poor understanding of what filehandles really were; but now after reading up on symbol tables I think I have that part fairly clear. What I am wondering is if there is a much better way to do this... or maybe there is already a module that does this, but I couldn't find one. Here is what I have come up with so far:

# I am running with perl -w && strict BTW sub read_file_or_handle { my $file_or_handle = shift; chomp $file_or_handle; unless(open FH, $file_or_handle ) { no strict q(refs); *FH = *file_or_handle; } while (<FH>) { ... } close FH; # closes it no matter what is was, right? # return something I read }

One thing I don't like about this right away is that I am assuming I have an open filehandle based on the failed call to open. I'm used to more of an "open or die" construct, so I know that I'm opening my self up to trouble right there. Suggestions?

Replies are listed 'Best First'.
Re: test if a scalar contains a filename or a filehandle?
by Cyrnus (Monk) on Apr 26, 2002 at 07:08 UTC
    if I'm reading it right using your code if a file exists with the same name as an open filehandle it will ignore the existing filehandle and open the file (which is not what you want). You should really test to see if the parameter is an already open filehandle. You can do this like so:
    if (fileno $file_or_handle) { # $file_or_handle is a filehandle } else { # $file_or_handle is a file # test for existance and open }
    the fileno() function returns the file descriptor for an open filehandle or it returns undef if the filehandle is not open.

    John
Re: test if a scalar contains a filename or a filehandle?
by jmcnamara (Monsignor) on Apr 26, 2002 at 08:07 UTC
Re: test if a scalar contains a filename or a filehandle?
by rjray (Chaplain) on Apr 26, 2002 at 06:51 UTC

    For starters, I would recommend that you test for a filehandle before you try opening it as a file.

    Now, having said that, there shouldn't be very many ways in which you would get a scalar that holds a reference to a filehandle. I'm hoping that there is some degree of control over the calling syntax of your routine. In general, if your scalar is a reference to GLOB or something that derives from it (test with "UNIVERSAL::isa($file_or_handle, 'GLOB')"), then it's a filehandle. This will hold true for objects instantiated from the IO::File class (or any of the IO::Handle tree).

    And if that test returns false, then you are free to open it as a file. Pending tests for validity, of course :-).

    --rjray

Re: test if a scalar contains a filename or a filehandle?
by jmcnamara (Monsignor) on Apr 30, 2002 at 08:13 UTC

    I just noticed that the Scalar::Util module by gbarr recently added a function called openhandle().

    From the pod:

    openhandle FH Returns FH if FH may be used as a filehandle and is open, or FH is a tied handle. Otherwise undef is returned. $fh = openhandle(*STDIN); # \*STDIN $fh = openhandle(\*STDIN); # \*STDIN $fh = openhandle(*NOTOPEN); # undef $fh = openhandle("scalar"); # undef
    It uses several methods, including fileno(), to try to determine if the scalar is a valif FH.

    --
    John.