views:

1948

answers:

7

I am getting this error while executing my Perl script. Please, tell me how to rectify this error in Perl.

print() on closed filehandle MYFILE

This is the code that is giving the error:

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

I hope that now I'm clearer.

+11  A: 

You want to do some action on MYFILE after you (or the interpreter itself because of an error) closed it.

According to your code sample, the problem could be that open doesn't really open the file, the script may have no permission to write to the file.

Change your code to the following to see if there was an error:

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

Update

ysth pointed out that -w does not really good to check if you can write to the file, it only ‘checks that one of the relevant flags in the mode is set’. Furthermore, brian d foy told me that the conditional I've used isn't good to handle the error. So I removed the misleading code. Use the one above instead.

Török Gábor
I would prefer the three-argument open: open (MYFILE, '>', $file) ...
Svante
@Svante: thanks, Brad's just corrected that :)
Török Gábor
-w does not check that you can write to the file, it checks that one of the relevant flags in the mode is set. This may produce both false positives and false negatives. You are far better off just trying to open it for writing and detecting an open error.
ysth
Where is that if-else meme coming from? What does anyone expect $! to be in that else block? It's certainly nothing to do with the open.
brian d foy
@ysth @brian thank you for your comments. I updated my answer to reflect your remarks. It's been a while I do not use Perl regularly, sorry for the written mistakes.
Török Gábor
A: 

Somewhere in you're script you will be doing something like:

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

The last line will throw an error because MYFILE has been closed.

Update

After seeing your code, it looks like the file you are trying to write to can't be opened in the first place. As others have already mentioned try doing something like:

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

Which should give you some feedback on why you can't open the file.

Tom
i have writtem my code as well...............please see and help me with the solution
+2  A: 

This:

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

In modern Perl, it could be written as:

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

This way you get a $variable restricted to the scope, there is no "funky business" if you have weird filenames (e.g. starting with ">") and error handling (you can replace die with warn or with error handling code).

Once you close $file_fh or simply go out of scope, you can not longer print to it.

+8  A: 

It appears that the open call is failing. You should always check the status when opening a filehandle.

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;

If the open is unsuccessful, the built-in variable $! (a.k.a. $OS_ERROR) will contain the OS-depededant error message, e.g. "Permission denied"

It's also preferable (for non-archaic versions of Perl) to use the three-argument form of open and lexical filehandles:

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;
Michael Carman
I know it's in PBP, but I just can't get used to the look of `print {$fh} $DATA` for printing to filehandles. It just looks wrong.
Telemachus
+1  A: 

Check that the open worked

if(open(my $FH, ">", "filename") || die("error: $!"))
{
    print $FH "stuff";
    close($FH);
}
hpavc
You don't need the if() construct. When it's false you already die. :)
brian d foy
+2  A: 

An alternate solution to saying or die is to use the 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";

The code above produces the following error (unless a file named nsdfkjwefnbwef exists in the current directory):

Can't open 'nsdfkjwefnbwef' for reading: 'No such file or directory' at example.pl line 7
Chas. Owens
+1  A: 

If you use a global symbol MYFILE as your filehandle, rather than a local lexical ($myfile), you will invariably run into issues if your program is multithreaded, e.g. if it is running via mod_perl. One process could be closing the filehandle while another process is attempting to write to it. Using $myfile will avoid this issue as each instance will have its own local copy, but you will still run into issues where one process could overwrite the data that another is writing. Use flock() to lock the file while writing to it.

Ether