Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Open file issues

by hotshot (Prior)
on Aug 18, 2004 at 09:39 UTC ( [id://383906]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all!

I have the following function for openning a file:
sub openFile { my ($file, $accessMode) = @_; my $err; if (! defined($accessMode)) { # by default, open the file for re +ading $accessMode = $MODE_READ; } if (exists($ACCESS_MODES{$accessMode})) { if (! open(FILE, "$ACCESS_MODES{$accessMode}$file")) { $err = $!; if (defined($returnOnError)) { return $FALSE; } &throwGenError("Can't open $file: $err"); # throw except +ion } } else { &throwGenError("In openFile: Wrong access mode $accessMode"); } return FILE; }
The problem is when I call it in a function, and before closing the file handler I call another function the also opens a file (another file), for example:
sub func1 { my (@fileContent,@temp, @comment); my $contentFh = &openFile($file1); while (my $line = <$contentFh >) { ... push(@fileContent,&func2($line)); ... } } close($contentFh); return \@fileContent; } sub func2 { my ($user) = @_; my @groupsFile; my $groupsFh = &openFile($file2); @groupsFile = <$groupsFh>; close($groupsFh); ... return @groupsFile; }
When calling func1 I get the following errors to screen:
readline() on closed filehandle FILE at /var/www/cgi-bin/lib/myfile.pl + line 25.
It's the leine of the while(). It doesn't happen when I don't call func2 from within func1, I guess the close() call in func2 somehow effects func1.
Anywhy can explain the problem and suggest a solution?

Thanks a lot

Replies are listed 'Best First'.
Re: Open file issues
by davorg (Chancellor) on Aug 18, 2004 at 09:55 UTC

    If you were running with "use warnings" then Perl would have told you what the problem is. Filehandles aren't first-class variables in Perl so you can't just return a filehandle from a function and assign it to a variable like that. You're actually using the same filehandle (FILE) for both files - which is why you can't use it after you've closed the first filehandle.

    You can get round this by using lexical filehandles.

    sub openFile { my ($file, $accessMode) = @_; my $err; $accessMode = $MODE_READ unless defined $accessMode; if (exists($ACCESS_MODES{$accessMode})) { if (open(my $fh, "$ACCESS_MODES{$accessMode}$file")) { return $fh; } else { $err = $!; if (defined($returnOnError)) { return; } &throwGenError("Can't open $file: $err"); # throw exception } } else { &throwGenError("In openFile: Wrong access mode &accessMode"); } return; }

    Some of your logic is a bit scary, so I haven't changed too much. You might need to check it carefully.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Some of your logic is a bit scary, so I haven't changed too much. You might need to check it carefully. Can you explain what you ment?

      And thanks for your pre answer

        Oh, I just mean that there are a few globals which make me a bit uncomfortable and your error handling is (to my eyes) a bit bizarre. The more "Perlish" approach would be to return a false value for smaller errors and to just die on fatal stuff.

        --
        <http://www.dave.org.uk>

        "The first rule of Perl club is you do not talk about Perl club."
        -- Chip Salzenberg

Re: Open file issues
by eserte (Deacon) on Aug 18, 2004 at 09:55 UTC
    All the files in your script share one filehandle, FILE. You have two options to solve this problem: use Symbol::gensym() to create unique filehandles, or use lexicals instead of bareword filehandles. The latter option requires you to have a new perl (5.6 or 5.8, I can't remember). The code would look like this:
    my $fh; open($fh, "...") or die ...; return $fh;

      You could also use IO::File which should work in even older perls.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://383906]
Approved by eserte
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2024-04-19 23:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found