Why am I getting a closed file descriptor error when using the diamond operator in a 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; .... } 

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

+4
source share
2 answers

You have a typo in the code you submitted (second open argument), but this does not explain the error message. The message for this problem will be as follows:

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

Your problem is related to priority. || binds too tightly, forcing Perl to process this entire expression as the third argument to open:

 $file || croak $! 

As a result, despite the fact that open does not work (probably because $file not a valid file name), croak fails (because $file is true and || short-circuit). After open fails, your program tries to read some lines from an unopened file descriptor, and you get this error message:

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

Instead, you want to use one of the following. The second option works (unlike your code), because or has a low priority.

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

See perlop for more information on operator precedence . The relevant point in your case is that the || has a higher priority than the list separator (comma).

+11
source

There is a typo in the 2nd argument:

 open my $fh, '<', $file || croak "Could not open file $file!\n"; 
+1
source

Source: https://habr.com/ru/post/1307863/


All Articles