Почему я получаю закрытую ошибку дескриптора файла при использовании оператора diamond в контексте списка в Perl? - PullRequest
4 голосов
/ 24 апреля 2010

Этот код:

foreach my $file (@data_files) {

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

    ....

}

выдает эту ошибку:

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

и я понятия не имею, почему.

РЕДАКТИРОВАТЬ: в исходной записи open исходное сообщение содержало ',' вместо '<.

Ответы [ 2 ]

11 голосов
/ 24 апреля 2010

У вас есть опечатка в коде, который вы опубликовали (второй аргумент open), но это не объясняет сообщение об ошибке. Сообщение для этой проблемы будет следующим:

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

Ваша проблема связана с приоритетом. || связывается слишком тесно, в результате чего Perl рассматривает все это выражение как третий аргумент для открытия:

$file || croak $!

В результате, даже если open завершается ошибкой (вероятно, из-за того, что $file не является допустимым именем файла), croak не выполняется (потому что $file имеет значение true и || короткое замыкание). После сбоя open ваша программа пытается прочитать некоторые строки из неоткрытого дескриптора файла, и вы получите следующее сообщение об ошибке:

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

Вы хотите использовать одно из следующих. Второй вариант работает (в отличие от вашего кода), поскольку or имеет низкий приоритет.

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

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

Подробнее о приоритетах операторов см. perlop . Важным моментом в вашем случае является то, что оператор || имеет более высокий приоритет, чем разделитель списка (запятая).

1 голос
/ 24 апреля 2010

Во втором аргументе есть опечатка:

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