...and including $! in the error message is the postmodern way ;)
open my $f1, '<', $file1
or die "Cannot open file '$file1': $!";
| [reply] [d/l] [select] |
use English qw( -no_match_vars );
open my $f1, '<', $file1
or die "Cannot open file '$file1': $OS_ERROR\n";
| [reply] [d/l] |
use autodie qw[ open ];
open my $F1, '<', $file1;
| [reply] [d/l] |
I'm new to Perl as well, and all of the examples that I've come across instruct you to open a file like this:
open (FH, "<$file1") or die "blahblah";
Would you (or anyone for that matter) mind elaborating as to why 1) and 2) should be used?
Much appreciated in advance.
| [reply] [d/l] |
See the first four items of Perl Best Practices Chapter 10 (I/O), namely:
- Don't use bareword filehandles
- Use indirect filehandles
- If you have to use a package filehandle, localize it first
- Use either the IO::File module or the three-argument form of open
Using lexical file handles is better style because:
- They are local variables and so avoid the generally evil programming practice of keeping state in global variables.
- They close themselves automatically when their lexical variable goes out of scope.
- They avoid the confusion of barewords. IMHO, barewords are an unfortunate Perl feature. Admittedly, they're handy when writing poems or playing golf. Historically, they probably exist only because of the improbable chance circumstance of Larry sitting right next to a brilliant poet (Sharon Hopkins) when designing early versions of Perl at JPL in the early 1990s and being led astray by her beautiful poetry readings.
The old two-argument form of open is subject to various security exploits as described
at Opening files securely in Perl.
| [reply] [d/l] |
With open (FH, "<$file1") or die "blahblah"; there is a possible security issue because maybe the variable $file1 might contain something that would cause problems. What goes in to the open() function is the interpolated string. You learned right, always use the < or > etc. In your example, if $file1 was ">ImportantFile", the open() will fail because the argument would evaluate to "<>ImportantFile" and open() won't like that filename! If you forgot the "<", then then open to ">ImportantFile" might succeed and it would be deleted or other various bad things could happen.
So if you use: open (FH, '<', $file1) || die; putting the file mode explicitly there is a "small" thing that could save you big problems later.
If you are writing small one or two page programs, using a bare word like FH is no big deal. However, be aware that Perl like C (you have do it this way in C), can use lexical variables for filehandles. So you can open($infile, '<', $somefile)... and pass $infile to a subroutine just like any other Perl variable.
As far as $! in "die" messages, you might or might not want to put that there. Part of this depends upon how descriptive your part of the "die" message is! Ok, try some code:
#!/usr/bin/perl -w
use strict;
open(FH, '<', "bad") || die "your textXXX OS says: $!\n";
while (<FH>){} # prevents warning FH only used once
See what $! has to say. My OS prints, "your textXXX OS says: No such file or directory". I figure that "your textXXX" is way more important. Something like "can't open Budget.csv" is way more to the point than "No such file or directory"- most of the time the OS text is meaningless for the average user. Also notice what adding the trailing "\n" to the die message does.
Update: This thread has morphed into something else from the OP's original question. But I figure it is ok to comment on some of the comments to the comments! | [reply] [d/l] [select] |
| [reply] |