Как разрешить ошибку "print() при закрытии файла" в Perl?

Я получаю эту ошибку при выполнении моего Perl script. Пожалуйста, скажите мне, как исправить эту ошибку в 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;
}

Я надеюсь, что теперь я понятнее.

Ответ 1

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

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

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

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

Update

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

Ответ 2

Похоже, что вызов 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;

Если open не увенчался успехом, встроенная переменная $! (a.k.a. $OS_ERROR) будет содержать сообщение об ошибке OS-depededant, например. "Разрешение отклонено"

Также предпочтительнее (для неархаичных версий 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;

Ответ 3

Альтернативным решением сказать 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

Ответ 4

Это:

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 или просто выходите из области видимости, вы не можете больше печатать на нем.

Ответ 5

Убедитесь, что открытая работа

if(open(my $FH, ">", "filename") || die("error: $!"))
{
    print $FH "stuff";
    close($FH);
}

Ответ 6

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

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

Ответ 7

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

Ответ 8

Где-то в тебе script вы будете делать что-то вроде:

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

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

Update

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

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

Который должен дать вам некоторые отзывы о том, почему вы не можете открыть файл.