2009-05-30 8 views
11

Je reçois cette erreur lors de l'exécution de mon script Perl. S'il vous plaît, dites-moi comment corriger cette erreur dans Perl.Comment résoudre une erreur "print() on closed filehandle" dans Perl?

print() on closed filehandle MYFILE 

C'est le code qui donne l'erreur:

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; 
} 

J'espère que maintenant je suis plus claire.

+1

Le titre du message doit être modifié. On dirait que c'est une erreur dans Perl! –

+1

serait utile si l'avertissement de perl "print() sur le fichier fermé" message a également suggéré de vérifier le handle de fichier pourrait être ouvert ou non –

Répondre

29

Vous voulez effectuer une action sur MYFILE après que vous (ou l'interpréteur lui-même à cause d'une erreur) l'ayez fermé.

Selon votre exemple de code, le problème pourrait être que open n'ouvre pas vraiment le fichier, le script peut ne pas avoir l'autorisation d'écrire dans le fichier.

Changer votre code à ce qui suit pour voir s'il y avait une erreur:

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

Mise à jour

ysth a souligné que -w est pas vraiment bon à vérifier si vous pouvez écrire dans le fichier , il vérifie seulement que l'un des drapeaux pertinents dans le mode est défini. En outre, brian d foy m'a dit que le conditionnel que j'ai utilisé n'est pas bon pour gérer l'erreur. J'ai donc supprimé le code trompeur. Utilisez le code ci-dessus à la place.

+1

Je préférerais les trois arguments ouverts: ouvrir (MYFILE, '>', $ fichier) ... – Svante

+0

@Svante: merci, Brad vient de corriger cela :) –

+0

-w ne vérifie pas que vous pouvez écrire dans le fichier, il vérifie que l'un des indicateurs pertinents dans le mode est défini. Cela peut produire à la fois des faux positifs et des faux négatifs. Vous êtes bien mieux d'essayer de l'ouvrir pour écrire et détecter une erreur ouverte. – ysth

1

Quelque part vous êtes script que vous allez faire quelque chose comme:

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

La dernière ligne lancera une erreur car MYFILE a été fermé.

Mise à jour

Après avoir vu votre code, il semble que le fichier que vous essayez d'écrire ne peut pas être ouvert en premier lieu. Comme d'autres l'ont déjà mentionné, essayez de faire quelque chose comme:

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

Ce qui devrait vous donner des informations sur les raisons pour lesquelles vous ne pouvez pas ouvrir le fichier.

+0

J'ai aussi écrit mon code ............... s'il vous plaît voir et m'aider avec la solution –

3

Ce:

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

En modern Perl, il pourrait être écrit:

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

De cette façon, vous obtenez une variable $ limitée à la portée, il n'y a pas "entreprise géniale" si vous avoir des noms de fichiers bizarres (par exemple commençant par ">") et la gestion des erreurs (vous pouvez remplacer die avec warn ou avec le code de gestion des erreurs). Une fois que vous fermez $ file_fh ou êtes simplement hors de portée, vous ne pouvez plus imprimer dessus.

12

Il semble que l'appel open échoue. Vous devez toujours vérifier l'état lors de l'ouverture d'un descripteur de fichier.

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; 

Si l'ouverture est infructueuse, la variable intégrée $! (a.k.a. $ OS_ERROR) contiendra le message d'erreur de déporté OS, par ex. « Autorisation refusée »

Il est également préférable (pour les versions non archaïques de Perl) d'utiliser la forme à trois arguments de open et des descripteurs de fichier lexical:

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; 
+0

Je sais que c'est en PBP, mais je ne peux pas m'habituer à l'apparence de 'print {$ fh} $ DATA' pour l'impression dans les handles de fichiers. Cela semble juste faux. – Telemachus

3

Vérifiez que l'ouverture a travaillé

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

Vous n'avez pas besoin de la construction if(). Quand c'est faux, vous mourez déjà. :) –

6

Une solution alternative à dire or die est d'utiliser le 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"; 

Le code produit ci-dessus l'erreur suivante (à moins qu'un fichier nommé existe nsdfkjwefnbwef dans le répertoire courant):

Can't open 'nsdfkjwefnbwef' for reading: 'No such file or directory' at example.pl line 7 
2

Si vous utilisez un MYFILE global de symbole comme descripteur de fichier, plutôt que d'un lexique local (mon_fic $), vous rencontrerez invariablement des problèmes si votre programme est multithread, par exemple s'il est exécuté via mod_perl. Un processus peut fermer le handle de fichier alors qu'un autre processus tente d'y écrire. L'utilisation de $ myfile évitera ce problème car chaque instance aura sa propre copie locale, mais vous rencontrerez toujours des problèmes où un processus pourrait écraser les données écrites par un autre. Utilisez flock() pour verrouiller le fichier tout en écrivant dessus.

3

J'ai rencontré ce problème lorsque mes fichiers ont été définis sur LECTURE SEULE. Vérifiez également ceci, avant d'abandonner! :)

Questions connexes