views:

109

answers:

2

This code:

foreach my $file (@data_files) {

    open my $fh, '<', $file || croak "Could not open file $file!\n";
    my @records = <$fh>;
    close $fh;

    ....

}

produces this error:

readline() on closed filehandle $fh at nut_init_insert.pl line 29.

and I have no idea why.

EDIT: The original post had ',' instead of '<' in the open statement.

+1  A: 

There is a typo in 2nd argument to open:

open my $fh, '<', $file || croak "Could not open file $file!\n";
el.pescado
TFGITW ... +1:)
DVK
The typo is in the question but not the code.
gvkv
Aways create a minimal but complete program and show us the real code. Otherwise, you waste people's time fixing problems you don't actually have.
brian d foy
The snippet meets your criteria. Mistakes happen. FM gave a great answer and I learned something about precedence. Win-win.
gvkv
+10  A: 

You have a typo in the code you posted (the second arg to open), but that does not explain the error message. The message for that problem would be this:

Unknown open() mode ',' at ...

Your problem is related to precedence. The || binds too tightly, causing Perl to treat this entire expression as the 3rd argument to open:

$file || croak $!

As a result, even though open fails (probably because $file is not a valid file name), croak is not executed (because $file is true and the || short-circuits). After the open fails, your program tries to read some lines from an unopened file handle, and you get this error message:

readline() on closed filehandle $fh at ...

You want to use one of the following instead. The second option works (unlike your code) because or is low precedence.

open(my $fh, '<', $file) || croak ...;

open my $fh, '<', $file or croak ...;

For details on operator precedence, see perlop. The relevant point in your case is that the || operator has higher precedence than the list separator (comma).

FM