Как устранить ошибку «print () для закрытого дескриптора файла» в Perl? - PullRequest
12 голосов
/ 30 мая 2009

Я получаю эту ошибку при выполнении сценария Perl. Подскажите, пожалуйста, как исправить эту ошибку в Perl.

print() on closed filehandle MYFILE

Это код, который выдает ошибку:

sub return_error
{
    $DATA= "Sorry this page is corrently being updated...<p>";
    $DATA.=  "<A href=\"javascript:history.go(-1)\"> Back </A>";
    open(MYFILE,">/home/abc/xrt/sdf/news/top.html");
    print MYFILE $DATA;
    close(MYFILE);
    exit;
}

Надеюсь, теперь я прояснил.

Ответы [ 8 ]

30 голосов
/ 30 мая 2009

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

Согласно вашему примеру кода, проблема может заключаться в том, что open на самом деле не открывает файл, возможно, у сценария нет разрешения на запись в файл.

Измените свой код на следующий, чтобы увидеть, если произошла ошибка:

open(MYFILE, ">", "/home/abc/xrt/sdf/news/top.html") or die "Couldn't open: $!";

Обновление

ysth указал, что -w не очень хорош при проверке возможности записи в файл, он только «проверяет, установлен ли один из соответствующих флагов в режиме». Кроме того, Брайан Д. Фой сказал мне, что использованное мною условие плохо подходит для обработки ошибки. Поэтому я удалил вводящий в заблуждение код. Вместо этого используйте код выше.

13 голосов
/ 30 мая 2009

Похоже, что вызов open сбой. Вы должны всегда проверять статус при открытии дескриптора файла.

my $file = '/home/abc/xrt/sdf/news/top.html';
open(MYFILE, ">$file") or die "Can't write to file '$file' [$!]\n";
print MYFILE $DATA;
close MYFILE;

Если открытие не удачно, встроенная переменная $! (a.k.a. $ OS_ERROR) будет содержать зависящее от ОС сообщение об ошибке, например, «В доступе отказано»

Также предпочтительно (для неархаичных версий Perl) использовать форму с тремя аргументами open и лексические файловые дескрипторы:

my $file = '/home/abc/xrt/sdf/news/top.html';
open(my $fh, '>', $file) or die "Can't write to file '$file' [$!]\n";
print {$fh} $DATA;
close $fh;
6 голосов
/ 30 мая 2009

Альтернативным решением для высказывания or die является использование autodie pragma:

#!/usr/bin/perl

use strict;
use warnings;
use autodie;

open my $fh, "<", "nsdfkjwefnbwef";

print "should never get here (unless you named files weirdly)\n";

Приведенный выше код вызывает следующую ошибку (если в текущем каталоге не существует файла с именем nsdfkjwefnbwef):

Can't open 'nsdfkjwefnbwef' for reading: 'No such file or directory' at example.pl line 7
3 голосов
/ 29 июля 2011

У меня была эта проблема, когда мои файлы были установлены только для чтения.

Проверьте это также, прежде чем сдаться! :)

3 голосов
/ 30 мая 2009

Проверьте, что открытое сработало

if(open(my $FH, ">", "filename") || die("error: $!"))
{
    print $FH "stuff";
    close($FH);
}
3 голосов
/ 30 мая 2009

Это:

open(MYFILE,">/home/abc/xrt/sdf/news/top.html");

В современном Perl это можно записать как:

open(my $file_fh, ">", "/home/abc/xrt/sdf/news/top.html") or die($!);

Таким образом, вы получаете переменную $, ограниченную областью действия, не существует «фанки», если у вас странные имена файлов (например, начинаются с «>») и обработки ошибок (вы можете заменить die на предупреждение или код обработки ошибок ).

Как только вы закроете $ file_fh или просто выйдете из области видимости, вы больше не сможете печатать на нем.

2 голосов
/ 01 июня 2009

Если вы используете глобальный символ MYFILE в качестве дескриптора файла, а не локальный лексический ($ myfile), вы непременно столкнетесь с проблемами, если ваша программа многопоточная, например, если он работает через mod_perl. Один процесс может закрывать дескриптор файла, в то время как другой процесс пытается записать в него. Использование $ myfile позволит избежать этой проблемы, поскольку каждый экземпляр будет иметь свою собственную локальную копию, но вы все равно столкнетесь с проблемами, когда один процесс может перезаписать данные, которые пишет другой. Используйте flock () для блокировки файла во время записи в него.

1 голос
/ 30 мая 2009

Где-то в вашем скрипте вы будете делать что-то вроде:

open MYFILE, "> myfile.txt";
# do stuff with myfile
close MYFILE;
print MYFILE "Some more stuff I want to write to myfile";

Последняя строка выдаст ошибку, потому что MYFILE был закрыт.

Обновление

После просмотра вашего кода, похоже, что файл, который вы пытаетесь записать, не может быть открыт в первую очередь. Как уже упоминали другие, попробуйте сделать что-то вроде:

open MYFILE, "> myfile.txt" or die "Can't open myfile.txt: $!\n"

Что должно дать вам обратную связь о том, почему вы не можете открыть файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...