tags:

views:

92

answers:

3

I am having some trouble trying to print from a file. Any ideas? Thanks

open(STDOUT,">/home/int420_101a05/shttpd/htdocs/receipt.html"); 
#Results of a sub-routine
&printReceipt; 
close(STDOUT);

open(INF,"/home/int420_101a05/shttpd/htdocs/receipt.html"); $emailBody = <INF>; 
close(INF); 
print $emailBody;

ERRORS: Filehandle STDOUT reopened as INF only for input at ./test.c line 6. 
print() on closed filehandle STDOUT at ./test.c line 9.
A: 

Don't try to open the STDOUT handle. If you want to print to STDOUT, just use print (with no filehandle argument). If you want to print to something other than STDOUT, use a different name.

JSBangs
+4  A: 
  1. This discussion addresses the technical reason for the message. Relevant info from the thread is this:

    From open(2) manpage:

    When the call is successful, the file descriptor returned will be the lowest file descriptor not currently open for the process.

    But STDOUT still refers to the filehandle #1. This warning could be useful. Although one can argue that further uses of STDOUT as an output filehandle will trigger a warning as well...

    So, to summarize, you closed STDOUT (file descriptor 1) and your file will be open as FD#1. That's due to open()'s properties.

  2. As other have noted, the real reason you're having this problem is that you should not use STDOUT for printing to a file unless there's some special case where it's required.

    Instead, open a file for writing using a new file handle:

    open(OUTFILE,">/home/int420_101a05/shttpd/htdocs/receipt.html")
       || die "Could not open: $!"; 
    print OUTFILE "data";
    close(OUTFILE);
 
  1. To print to filehandle from subroutine, just pass the file handle as a parameter.

    The best way of doing so is to create an IO::File object and pass that object around

  my $filehandle = IO::File->new(">$filename") || die "error: $!";
  mySub($filehandle);

  sub mySub {
     my $fh = shift;
     print $fh "stuff" || die "could not print $!";    
  }
 

You can also set a particular filehandle as a default filehandle to have print print to that by default using select but that is a LOT more fragile and should be avoidded in favor of IO::File solution.

DVK
The thing is that i want to print the results of a subroutine... is there any way I can accomplish this?
alexBrand
What you want to do is `select FILEHANDLE`. The `select` call sets a new filehandle as the default destination for print calls.
JSBangs
@alexBrand - Added the info on how to print properly in a subroutine
DVK
+1  A: 

If you want to temporarily change the standard output, use the select builtin. Another option is to localize the typeglob first:

{
    local *STDOUT;
    open STDOUT, '>', 'outfile.txt' or die $!;
    print "Sent to file\n";
}
eugene y
The thing is i am trying to print the results of a subroutine to the file... I just changed the code.. sorry
alexBrand