Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting a closed filehandle error when using the diamond operator in list context in Perl?

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.

like image 825
gvkv Avatar asked Dec 18 '22 01:12

gvkv


2 Answers

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).

like image 169
FMc Avatar answered Dec 19 '22 14:12

FMc


There is a typo in 2nd argument to open:

open my $fh, '<', $file || croak "Could not open file $file!\n";
like image 29
el.pescado - нет войне Avatar answered Dec 19 '22 15:12

el.pescado - нет войне