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

First of all, I'd like to say all documentation I've read on using filehandles is extremely confusing to me, and since I didn't understand it I tried to use one to see if I could figure it out. Thus my question.

#!/usr/bin/perl #this program is supposed to take user input put it into an array and +then add #that text into a log file. use 5.010; use strict; print "Enter some text then hit control+D and we\'ll try to send it to + the perlogfile:\n"; my @stuff = <STDIN>; open (LOG, ">>perlogfile.rtf"); #error always happens here :no such file or directory if (! open LOG ) { die "cannot create link to logfile: $!"; } print LOG "@stuff"; close (LOG);

the error from terminal is cannot create link to logfile: No such file or directory at /private/var/folders/EZ/EZjgQkjmGqen0F4rMB61CU+++TI/Cleanup At Startup/filehandletest-288591461.705.pl line 11, <STDIN> line 1.

I dont know why it's trying to look in some temp folder in the first place, but I even went there and pasted my "perlogfile" into that folder. still the SAME error.

I do have permission to read/write to this file.

What am I doing wrong?

Replies are listed 'Best First'.
Re: Can't get a simple log creator to work!
by jwkrahn (Abbot) on Feb 23, 2010 at 05:39 UTC
    if (! open LOG ) {

    That line is equivalent to:

    if (! open LOG, '<', $main::LOG ) {

    And since you didn't store a file name in $main::LOG the open will fail.

      my perl book didn't say anything about that, really the filehandles section made no sense (this is the o'reilley book). how do i use $main::LOG to store a filename to it? (it would be the name of the log file in this case right?)
        Which O'reilley book?

        I suggest you start with perlintro, and perlopentut, but basically

        open my($fh), '>', '/f/o/o' or die "Can't clobber /f/o/o : $!"; print $fh "stuff\n"; ...
        or the slick version
        use autodie; open my($fh), '>' '/f/o/o'; print $fh "stuff\n"; ...
Re: Can't get a simple log creator to work!
by ikegami (Patriarch) on Feb 23, 2010 at 05:29 UTC
    You're opening the file twice, the second time using some arcane method.
    #!/usr/bin/perl use 5.010; use strict; use warnings; my $fn_log = 'perlogfile.rtf'; open(my $fh_log, '>>', $fn_log) or die("Can't append to log file \"$fn_log\": $!\n"); print($fh_log $_) while <STDIN>;
      thanks but it's not putting what i enter into terminal into that file. (but no wierd error that I don't understand at least) but this is *supposed* to send <STDIN> to $fh_log (what's the H for?) until end-of-file and append fh_log to fn_log correct?

        thanks but it's not putting what i enter into terminal into that file.

        Yes it does.

        >perl a.pl fasfd dsfdasfdasf dsafsdafdas fdasfdasfs ^Z >type perlogfile.rtf fasfd dsfdasfdasf dsafsdafdas fdasfdasfs

        Perhaps you are peeking at the file before you stop adding to it, in which case you are suffering from buffering. Fix:

        #!/usr/bin/perl use 5.010; use strict; use warnings; use IO::Handle qw( ); my $fn_log = 'perlogfile.rtf'; open(my $fh_log, '>>', $fn_log) or die("Can't append to log file \"$fn_log\": $!\n"); $fh_log->autoflush(1); print($fh_log $_) while <STDIN>;

        fh = file handle

        fn = file name. But it's actually used as a qualified file name, such as an absolute path (/foo/bar/file.txt) or a relative path (file.txt or baz/file.txt or ../qux/file.txt)

Re: Can't get a simple log creator to work!
by cdarke (Prior) on Feb 23, 2010 at 11:32 UTC
    Just commenting out the second open works for me, but there are still problems with your script.

    You use strict; which is good, but you should also use warnings;
    Giving the filename the suffix ".rtf" does not make it a rich text file, it is just a plain text file (apologies if you knew that).
    When you print "@stuff" the action of the double quotes is to place (by default) a space between each element, and this will appear in the file.
    Here is a tided version:
    #!/usr/bin/perl #this program is supposed to take user input put it into an array and +then add #that text into a log file. use 5.010; use strict; use warnings; print "Enter some text then hit control+D and we'll try to send it to +the perlogfile:\n"; my @stuff = <STDIN>; open (LOG, '>>', 'perlogfile.rtf') or die "Unable to open logfile: $!" +; print LOG @stuff; close (LOG);


    File handle
    When a program asks the operating system to use a file (open) then several checks have to be made. Obviously it has to find where the physical file is, but it also has to check the file permissions against (on UNIX) the process's user id and maybe group id. To do that (again, on UNIX) it has to read from disc the file's inode. Clearly all that is a lot of work and takes time. If we had to do that every time we wanted to write a line to a file then things would be slow. So, we open the file just once and store all that information internally in RAM, so that it can be referred to whenever we want to write to the file. The file handle is our reference to that internal information, so we use that each time we access the file.
    Downside is that this information uses up memory, so we tidy it all up when we do a close.

    Perl is not alone in using this mechanism - most programming languages do something similar. To complicate matters, there are (at least) two ways to describe a file handle. You are using the old-fashioned way with an uppercase global name - LOG. That's often good enough, and still very commonly used. A more modern way is to use a lexical variable, which has the advantage (among others) of not being global - important in a large multi-file application
    open (my $fh, '>>', 'perlogfile.rtf') or die "Unable to open logfile: +$!"; print $fh @stuff; close ($fh);
Re: Can't get a simple log creator to work!
by Anonymous Monk on Feb 23, 2010 at 05:15 UTC
    What do you think if (! open LOG ) {die "cannot create link to logfile: $!";} does?
      tells the program that if the filehandle LOG fails to initialize to print the error message
        tells the program that if the filehandle LOG fails to initialize to print the error message
        May I ask you where you get this idea?

        If you want to know whether the open failed, you need to check the return code of the open function which you used to open the file. If it is false (i.e. undef, 0 or ''), the error message can be found in "$!".

        -- 
        Ronald Fischer <ynnor@mm.st>