michellem has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I'm sure this problem is due to my ignorance of these issues, but I'm puzzled by this. I have a script, where I want to give the user the option of saving the output (from a database) to a file (which will eventually generate a pdf), or showing it in the browser. I'm using CGI.pm mostly for the output. I can get one or the other, but can't get both. Here's a bit of the code I'm working on:

if ($query{submit} eq "PDF") { open STDOUT, ">tempfile.html" or graceful_exit("can't open fil +e"); }
Then there are a bunch of print statements, and the like, and then I close STDOUT.

Choosing to display the output ($query{submit} equals "HTML" in that case), works fine, but if PDF is chosen, the file is empty. (There are no permissions or filesystem issues.

If, instead I use the following code:

if ($query{submit} eq "PDF") { open OUTPUT, ">tempfile.html" or graceful_exit("can't open fil +e"); } else { open OUTPUT, '>STDOUT'; # I know this is wrong }
Followed by print OUTPUT statements, the file gets created fine, but there is no output to the web browser.

I can't seem to find anywhere (perlopentuit or the camel book), the syntax on an open statement that allows me to open STDOUT as a regular filehandle.

I'm stumped. Because the output is generated from database output and manipluation of that data, I don't want to create redundant sets of print statements, one to a file and the other to the browser. The other option I could choose is to put this all in a subroutine, and then send the output to one or another place, depending on choice. But this seems like it ought to be straightforward.

Thanks!

Replies are listed 'Best First'.
Re: Redirection of output
by sgifford (Prior) on Sep 09, 2003 at 17:52 UTC

    For your second try, what you want is:

    open(OUTPUT,">&STDOUT") or die "couldn't dup stdout: $!";
    This is documented in perldoc -f open.

    You can also accomplish what you want with the one-argument form of select. See perldoc -f select.

    But I'm not sure why your first attempt won't work. This works fine for me:

    #!/usr/bin/perl open(STDOUT,">/tmp/tempfile.html") or die "open: $!"; foreach my $i (1..10) { print $i,"\n"; }

    Can you reduce your program to a smaller testcase and see if you can still reproduce the problem? Or can you reproduce the problem from the command-line and see what's going on?

      Thanks, that works. I think my confusion about using the ">&STDOUT" syntax (that I did see in the camel book) had to do with duplication of STDOUT, which I didn't think I wanted. So it was just a matter of my ignorance of the issues.
Re: Redirection of output
by blue_cowdawg (Monsignor) on Sep 09, 2003 at 18:04 UTC

    Why not just re-open STDOUT such as:

    open(STDOUT,">tempfile.html",") or die $!;
    in the case(s) where you need to redirect to a file?

    If for some reason you want to preseve STDOUT you can also do the following:

    use FileHandle; my $fh=new FileHandle; if ($use_a_file) { $fh=open(">tempfile.html","w") or die !: } else { $fh->fdopen(STDOUT,"w"); } print $fh "blahblahblahblah\n";

    One last thought of a cautionary nature, make sure your CGI environment has permissions to open a file for writing in the directory you are attempting to do so.

    I'm sure there are more ways of doing this...


    Peter L. Berghold -- Unix Professional
    Peter at Berghold dot Net
       Dog trainer, dog agility exhibitor, brewer of fine Belgian style ales. Happiness is a warm, tired, contented dog curled up at your side and a good Belgian ale in your chalice.
Re: Redirection of output
by flounder99 (Friar) on Sep 09, 2003 at 19:25 UTC
    I think you want to use select.
    if ($query{submit} eq "PDF") { open OUTPUT, ">tempfile.html" or graceful_exit("can't open fil +e"); select OUTPUT; } #This goes to tempfile.html if conditions are true STDOUT otherwise print "blah blah blah"; select STDOUT; print "blah blah blah"; #This goes to STDOUT

    --

    flounder

Re: Redirection of output
by dragonchild (Archbishop) on Sep 09, 2003 at 18:23 UTC
    Use IO::File and read those docs.

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.