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

Hi I’m quite new to Perl so my knowledge is a little grey in most areas. I have a problem with a script I’m attempting to write. I have created two subroutines which opens two Arrays in order to replace some text within the selected files. The script runs fine and all the files are updated but I get the following error message. "Filehandle STDOUT reopened as MYFILE only for input at vpenv line 44" I can't work out why.
#Updates web_setup sub vpenv { open(MYFILE, "$location/$dir/$site/$vpfile") || die "Unable to open fi +le: $!"; my @stuff=<MYFILE>; $stuff[0]="setenv DSCUSTOMER $db\n"; $stuff[1]="setenv DSSITENO $sno\n"; $stuff[2]="setenv DSCUSTID $sid\n"; open STDOUT, ">$location/$dir/$site/$vpfile" || die "Unable to Write t +o file: $! "; print @stuff; close(STDOUT); close(MYFILE); } #Updates database.form sub vpdb { open(MYFILE, "$location/$dir/$site/$vpdir/$vpdata") || die "Unable to +Open File: $ !"; my @thing=<MYFILE>; $thing[0]=".ARG DATABASE $db\n"; open STDOUT, ">$location/$dir/$site/$vpdir/$vpdata" || die "Unable to +Write to Fil e: $!"; print @thing; close(STDOUT); close(MYFILE); } &vpenv; &vpdb;

Replies are listed 'Best First'.
Re: Filehandle Error
by Anno (Deacon) on Jul 06, 2007 at 09:30 UTC
    The code you put up is hard to follow. A lot of variables are undeclared and there are lines missing. At the very least you should have indicated which line is line 44, where the error occurred.

    The problem is that you're closing STDOUT. If you do that the system file descriptor (1) for STDOUT becomes available. The next open() (in your line 44) picks up that file descriptor and tries to open a file for reading on it. That results in the warning (not error) you have seen.

    Anno

Re: Filehandle Error
by tirwhan (Abbot) on Jul 06, 2007 at 09:40 UTC

    Take a look at perldoc perldiag under the explanation for the error message (specifically "Filehandle %s reopened as %s only for input"). You're closing STDOUT, the subsequent open of MYFILE gets the STDOUT filehandle id, and since you're only opening that for reading Perl warns you about this seemingly erratic behaviour.

    While there's nothing per se wrong with your code there are a few areas where it could be improved. Here's an alternative version (which also avoids the warning by not opening a file as STDOUT, which I consider bad practice):

    sub vpenv { my $file = shift; open(my $readf,"<","$file") or die "Unable to open file: $!"; my @stuff=<$readf>; close($readf); $stuff[0]="setenv DSCUSTOMER $db\n"; $stuff[1]="setenv DSSITENO $sno\n"; $stuff[2]="setenv DSCUSTID $sid\n"; open (my $writef,">","$file") or die "Unable to Write to file: $!"; print $writef @stuff; close($writef); } #Updates database.form sub vpdb { my $file = shift; open(my $readf,"<","$file") or die "Unable to Open File: $!"; my @thing=<$readf>; close($readf); $thing[0]=".ARG DATABASE $db\n"; open(my $writef,">",$file") or die "Unable to Write to File: $!"; print $writef @thing; close($writef); } vpenv("$location/$dir/$site/$vpfile"); vpdb("$location/$dir/$site/$vpdir/$vpdata");

    Or, even better, using Tie::File:

    use Tie::File; sub vpenv { my $file = shift; tie my @stuff, 'Tie::File', $file or die "Unable to tie $file: $!"; $stuff[0]="setenv DSCUSTOMER $db\n"; $stuff[1]="setenv DSSITENO $sno\n"; $stuff[2]="setenv DSCUSTID $sid\n"; untie @stuff; } sub vpdb { my $file = shift; tie my @thing, 'Tie::File', $file or die "Unable to tie $file: $!"; $thing[0]=".ARG DATABASE $db\n"; untie @thing; } vpenv("$location/$dir/$site/$vpfile"); vpdb("$location/$dir/$site/$vpdir/$vpdata");

    All dogma is stupid.
      Hi I have re wrote my code using your example and it seems to have done the trick, I'll have to do a little more reading to fully understand the cahnges you have made. :) thanks for all your help much appreciated.