Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

It's friday, I can't think.

by Pearte (Beadle)
on Jul 14, 2000 at 23:59 UTC ( [id://22624]=perlquestion: print w/replies, xml ) Need Help??

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

I have a program with multiple subroutines. One of these subroutine needs to write to a file. The remaining need to write to the screen. How do I redirect STDOUT into a file for the one subroutine? And , more importantly, how do I get STDOUT to work properly again (writing to the screen) when I am finished writing with this particular subroutine? Thanks All.

Replies are listed 'Best First'.
(chromatic) Re: It's friday
by chromatic (Archbishop) on Jul 15, 2000 at 00:10 UTC
    The magic is in select:
    open (FILE, ">$filename") or die "Can't open: $!"; select(FILE); print "This will go in $filename.\n"; select(STDOUT); print "This will go where you expect it -- STDOUT!\n";
RE: It's friday, I can't think.
by Adam (Vicar) on Jul 15, 2000 at 00:28 UTC
    There are several ways. You can play with select() as per chromatic's or plaid's posts. But if you have control over the subroutines you are better off printing directly to the filehandle when that's what you want to do. I also wanted to point out that plaid preserved the old filehandle, but <sigh> he didn't check for success opening the filehandle. Having just run into an issue with this, I'll also suggest localizing the filehandle to the subroutine. So my suggestion:
    { my $i = 1; # Function static var... ooooh. sub Whatever { my $select = (defined $_[0]) ? $_[0] : 0; my $old_fh; local *FH; open FH, ">>$file" or die "Failed to open $file, $!"; if( $select ) { $old_fh = select FH }; print FH "$i This will go to $file\n"; print "$i This will go to $file if \$select($select) is true.\n"; if( $select ) { select $old_fh } close FH or die "Failed to close $file, $!"; $i++; } } Whatever(0); Whatever(1); # Now the second print goes to FH.
    I did some extra stuff there to make it more clear. The $i gets incremented with each call so you can differentiate the print outs. My first version of this post had the select before I opened the filehandle. I don't recommend that as any print between the select and the open would bomb. So I fixed my example.
Re: It's friday
by plaid (Chaplain) on Jul 15, 2000 at 00:11 UTC
    If you are writing these subroutines yourself, you should just write to a filehandle. open it somewhere and then just
    print FH $whatever;
    If these are subroutines that someone else wrote, and you really don't want to edit them, you could do something like
    open(FH, "output.txt"); my $oldfh = select(FH); sub_that_writes_to_file(); select $oldfh; # reset to whatever it was close FH;
    This will work provided that the sub doesn't explicitly do print STDOUT.
RE: It's friday, I can't think. (CMonster: redirect STDOUT)
by CMonster (Scribe) on Jul 15, 2000 at 01:07 UTC

    Oddly enough, I went through this process just yesterday. Small world.

    In my case, select didn't do the trick because I was calling a C shared object via SWIG that didn't obey my orders (and wouldn't shut up about it.) Instead, I used an old perlopentut trick which ended up looking a bit like this:

    open(SAVEOUT, ">&STDOUT"); open STDOUT, ">>$serverdir/ss_log"; my $result = SmartSockets::projpoll($server_name); print "Connection to smartsockets updated.\n"; close STDOUT; open(STDOUT, ">&SAVEOUT");

    It's not to be used other than as a last resort, but in this case the last resort was the only one that worked.

Re: It's friday
by infoninja (Friar) on Jul 15, 2000 at 00:09 UTC
    Best bet is to print to a filehandle for the subroutine requiring STDOUT going to a file, and then just use print alone (w/out the filehandle) for the rest of the subroutines.
RE: It's friday, I can't think.
by Anonymous Monk on Jul 15, 2000 at 20:21 UTC
    There is a Tee Module available at http://jenda.krynicky.cz/ which whill allow you to write to multiple files, STDOUT/STDERR with one print.
Re: It's friday
by Boogman (Scribe) on Jul 15, 2000 at 23:01 UTC
    You can also alias STDOUT to point to a file using typeglobs.

    open FILE, ">>file.txt" or die "Couldn't open file";<BR> *TEMP = *STDOUT;<BR> *STDOUT = *FILE;<BR> print STDOUT "I go to the file now...\n";<BR> *STDOUT = *TEMP;<BR>
    just got to be careful that you're not obliterating anything in the process...
RE: It's friday, I can't think.
by wardk (Deacon) on Jul 18, 2000 at 02:14 UTC
    You can always force printing to STDOUT by alway using the filehandle in the statement.
    my $file = "/x/y/zee" open FH, ">$file" or die "cannot open"; print FH "hello there to $file"; print STDOUT "hello there to STDOUT";
    no doubt there are more ways!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://22624]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-03-29 01:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found