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

Hey monks,

I had a question about file handles. I wanted to know the difference between the following two methods and wanted to know if one was better than the other and why

open SHAKESPEARE, "complete_works.txt" or die "The haunted grave of Shakespeare won't open: $!";
$sh = *SHAKESPEARE; open $sh, "complete_works.txt" or die "The haunted grave of Shakespeare won't open: $!";

P.S: When I tried the first method, I got an error (Inappropriate I/O control operation), but not when I used the second.

Thanks

Replies are listed 'Best First'.
Re: Perl fIle handles
by 7stud (Deacon) on Jun 15, 2011 at 20:44 UTC

    1) Always include the following at the top of your code:

    use strict; use warnings; use 5.010; #if you are using perl 5.10 or greater

    2) Don't use bareword file handles, like here:

    open SHAKESPEARE, "complete_works.txt" or die "The haunted grave of Shakespeare won't open: $!";

    A bareword filehandle is like a global variable, and global variables are bad because any part of your code can change a global variable, which makes debugging very difficult.

    3) The following is called a 'typeglob':

    *someName
    A typeglob represents every perl variable with the name someName. Remember that in perl, these are all different variables:
    $x -- scalar @x -- array %x -- hash &x -- subroutine (as well as a filehandle named x)

    You can have all those variables in your program at the same time and there is no conflict. A typeglob is a reference to all of them. Once again, a typeglob is too much like a global variable, so generally you shouldn't use them for filehandles. Typeglobs are an intermediate to advanced topic.

    4) Despite wind's recommendation, I would suggest that you always use the 3-arg form of open. If you want to read from a file, and you use the 2 arg form of open like this:

    my $file = 'out.txt' open my $sh, $file or die ...

    that will work fine. But suppose you are opening all the files in a directory, and $file gets set to the filename ">out.txt", well now you have a problem because the 2 arg form of open is going to open that file for writing. Sometimes it's better to be explicit with what you want to do in your code than rely on perl's implicit workings behind the scenes.

Re: Perl fIle handles
by wind (Priest) on Jun 15, 2011 at 16:58 UTC

    The second one, a lexical file handle, is better (although you can drop the first line). This is because the file handle is scoped and will be automatically closed and destroyed when perl leaves the block that created it.

    You can create a lexical file handle from a fileglob by just taking its reference:

    my $sh = \*SHAKESPEARE;

    But it is best to open the lexical file handle directly, and the three parameter form of open when write mode:

    open my $fh, $file or die "Can't open $file::$!";

      But it is best to open the lexical file handle directly, and the three parameter form of open when write mode:

      open my $fh, $file or die "Can't open $file::$!";
      Did you mean
       open my $fh, (some mode string of + < > >>), $file or die "Can't open $file::$!";
      ??


      Be Appropriate && Follow Your Curiosity

        No, actually I just wanted to demonstrate that he could include the my within the open statement, but I can see how you could think I was implying something else. It was up to him to simply read the docs for open to see how to use the three parameter form.

        Also, I'd advise against ever using the three parameter form of open when wanting read mode. It's much better to just let read mode be assumed so you don't risk putting the symbol in the wrong direction and overwriting your file.

        Just my .02

Re: Perl fIle handles
by 7stud (Deacon) on Jun 15, 2011 at 20:45 UTC
    dup, sorry.