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

I am writing a package that has a subroutine that creates a reference to a file handle so that it can be used later by another routine in the package. The code that creates the reference and saves it is:
sub setDestFile { my($self, $file) = @_; local(*F); open( F, ">$file"); $fh = \*F; $self->{'destfile'} = $fh; }
The routine that later uses this reference is:
sub output { my($self, $text) = @_; print $self->{'destfile'} "$text"; }
The above routine produces the following error when I try to run the program: String found where operator expected near "} "text"" (Missing operator before "$text"?) I tried to change the routine like this:
sub output { my($self, $text) = @_; my $fh = $self->{'destfile'}; print $fh "$text"; }
This change doesn't produce the error but nothing gets written to the file. HELP

Replies are listed 'Best First'.
Re: Using File Reference
by danboo (Beadle) on Apr 05, 2002 at 16:57 UTC
    From 'perldoc -f print':
    Note that if you're storing FILEHANDLES in an array or other expressio +n, you will have to use a block returning its value instead: print { $files[$i] } "stuff\n"; print { $OK ? STDOUT : STDERR } "stuff\n";
    This takes care of your parse error, but I'm not sure why your asignment to $fh didn't work. In my local testing it worked fine. I second Ovid's suggestions.

    Cheers,

    - danboo

(Ovid) Re: Using File Reference
by Ovid (Cardinal) on Apr 05, 2002 at 16:49 UTC

    I don't see any immediate error in your code, but here's a couple of things to think about. First, check the status of your open. If you failed to open the file, printing to the file will silently fail.

    sub setDestFile { my($self, $file) = @_; local(*F); open( F, ">$file") or die "Cannot open $file for writing: $!"; $fh = \*F; $self->{'destfile'} = $fh; }

    Next, munge your contructor to print a header right away. If the open is successful and you don't print a header (you can add an a die to print, also), then you know where to look for the problem.

    Lastly, in &output, print $text somewhere where you can see it (STDOUT or STDERR come to mind) in order to verify that you are actually passing something.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      This is the entire test program I am using:
      #!/usr/bin/perl package Test; use strict; sub new { my $class = shift; return bless {'destFile' => \*STDOUT}, $class; } sub open { my($self, $file) = @_; local(*F); open(F, ">$file") or die "cannot open $file for writing: $!"; $self->{destFile} = \*F; } sub output { my($self, $text) = @_; my $fh = $self->{destFile}; print "$text\n"; printf {$self->{destFile}} "$text\n"; } sub close { my $self = shift; close( $self->{destFile}); } package main; $a = Test->new; $a->open("HELLO"); $a->output("THIS IS THE LINE TO OUTPUT TO THE FILE"); $a->close; exit;
      This program will create the HELLO file in the current directory but it WILL NOT print the output line to it. ?????? IS there anything wrong here.
        Add a use warnings pragma to your program and you'll see that the file handle, Test::F, is not open at the time you try to write to it.

        It is closing automatically as it goes out of scope. I think what you want is just a typeglob, not a reference to it. Simply remove the \ from before the typeglob and all is fine.

        $self->{destFile} = *F;
        Cheers,

        - danboo

Re: Using File Reference
by perlplexer (Hermit) on Apr 05, 2002 at 17:07 UTC
    You can use the following approach
    sub setDestFile { my($self, $file) = @_; open(my $fh, ">$file"); $self->{'destfile'} = $fh; }

    --perlplexer