in reply to How can you check to see if a file handle is already open?

The best solution is to store them in an array:
my @handles; for ( 1...31) { open(my $new_fh, ">200712$_"), or die "Could not open $date $!\n"; push @handes, $new_fh; }

The file handles are closed automatically when they go out of scope (and no reference to them exists anymore), so you don't need to close them explictly.

But it's good style to close them anyway, because if your function becomes part of a larger program the opened file handles my suck up resources.

Replies are listed 'Best First'.
Re^2: How can you check to see if a file handle is already open?
by agent_smith (Scribe) on Jan 16, 2008 at 16:20 UTC
    Thanks for the info, but doesn't this still open possibly unnecessary file handles? Maybe I should elaborate, and perhaps ask forgiveness for not being detailed enough.
    while(<DATA>) { chomp; if ($_ =~ m#^(\d+)/(\d+)/(\d+)\s+.*admin2;user) { open(FH$3, ">$3.$2.$1"); print "$_\n" FH$3; } }


    The problem with the above, is FH$3 may already be open, and I don't want to try to reopen it.

    And the problem with my first example is that it may open files for which I have no data, for example there was no data on the 15th, but I had opened the file anyway ( resulting in an un-needed 0 length file.

    Thanks again, for the help

    agent_smith
      I could have made it clearer ;-)

      You can actually avoid opening all the file handles with a small sub:

      my %handles; sub handle_for_name { my $f = shift; if ($handles{$f}){ return $handles{$f}; } else { open my $h, '<', $f or die "Can't open file '$f': $!"; $hanldes{$f} = $h; return $h; } }

      And then whenever you need a file handle you just call that function that opens the file if it's not already opened.

      You can make that sub even smaller with a neat little trick:

      use Memoize; memoize("handle_for_name"); sub handle_for_name { my $f = shift; open my $h, '<', $f or die "Can't open file '$f': $!"; return $h; }

      That's magic, eh?

      To answer your original question: if you have a file handle in a lexical variable $h, you can use if ($fh){ print "file opened\n"}

      moritz's approach is the same I had in mind, but there's something else that you should care about: if the dataset contains dates for different months and years, you could run out of resources quite easily (i.e. too many open files).

      In these cases, FileCache is your friend ;-)

      Why not just use the IO::Handle package?

      Use the opened method. It will tell you if a file handle is opened and ready.

      try the following code...

      use strict; use warnings; use IO::Handle; open my $fh, '>', 'file' or die $!; test_fh($fh); close $fh or die $!; test_fh($fh); sub test_fh { my ($fh) = @_; if ($fh->opened()) { print "fh is opened and ready\n"; } else { print "fh is closed\n"; } return; }
        Limbic~Region++,

        That thread was perfect! Thank you for pointing it out.

        while(<INPUT>) { chomp $_; if ( $_ =~ m#^(\d+)/(\d+)/(\d+)\s+# ) { my $date = join( '', ( $3, $1, $2) ); if ( ! $file_handles{$date} ) { open($file_handles{$date}, ">>", "$output_dir/$date") +or die "Could not open $date for writing: $!\n"; print { $file_handles{$date} } "$_\n"; } elsif ( defined $file_handles{$date} ) { print { $file_handles{$date} } "$_\n"; } } }


        agent_smith