pod/perlopentut.pod.orig 2006-07-14 12:28:40.000000000 +0300
pod/perlopentut.pod 2006-07-14 13:26:54.000000000 +0300
@@ -2,6 +2,37 @@ =head1 NAME
perlopentut - tutorial on opening things in Perl
+=head1 Reading a file
+
+A few examples for the unpatient:
+
+Reading a file line by line:
+
+ open my $fh, "<", "data.txt" or die "Could not open data.txt: $!";
+ while (my $line = <$fh>) {
+ # chomp $line; # to get rid of trailing \n
+ # do something with $line
+ }
+
+If the name of the file is in a variable $filename :
+
+ open my $fh, "<", $filename or die "Could not open $filename: $!";
+ while (my $line = <$fh>) {
+ # chomp $line; # to get rid of trailing \n
+ # do something with $line
+ }
+
+To write to a file:
+
+ open my $out, ">", "outfile.txt" or die "Could not open outfile.txt: $!";
+ print $out "Say something nice\n";
+
+To append to a file:
+
+ open my $out, ">>", "outfile.txt" or die "Could not open outfile.txt: $!";
+ print $out "Add something nice\n";
+
+
=head1 DESCRIPTIN
Perl has two simple, built-in ways to open files: the shell way for
@@ -35,67 +66,63 @@ =head1 E<agravela shell
=head2 Simple
-The C<openfunction takes two arguments: the first is a filehandle,
-and the second is a single string comprising both what to open and how
-to open it. C<openreturns true when it works, and when it fails,
-returns a false value and sets the special variable C<$!to reflect
-the system error. If the filehandle was previously opened, it will
-be implicitly closed first.
+The C<openfunction takes three arguments: the first is a filehandle,
+the second is the mode (how to open) and the third is a single string
+containing what to open. C<openreturns true when it works. When it
+fails, returns a false value and sets the special variable C<$!to
+reflect the system error. If the filehandle was previously opened,
+it will be implicitly closed first.
For example:
- open(INF, "datafile") || die("can't open datafile: $!");
- open(INF, "< datafile") || die("can't open datafile: $!");
- open(RESULTS,"runstats") || die("can't open runstats: $!");
- open(LG, ">logfile ") || die("can't open logfile: $!");
+ open(my $info, "<", "datafile") || die("can't open datafile: $!");
+ open(my $results,">", "runstats") || die("can't open runstats: $!");
+ open(my $log, ">>", "logfile") || die("can't open logfile: $!");
If you prefer the low-punctuation version, you could write that this way:
- open INF, "< datafile" or die "can't open datafile: $!";
- open RESULTS,"runstats" or die "can't open runstats: $!";
- open LG, ">logfile " or die "can't open logfile: $!";
+ open my $info, "<", "datafile" or die "can't open datafile: $!";
+ open my $results,">", "runstats" or die "can't open runstats: $!";
+ open my $log, ">>", "logfile" or die "can't open logfile: $!";
-A few things to notice. First, the leading less-than is optional.
-If omitted, Perl assumes that you want to open the file for reading.
+ thing to notice:
-Note also that the first example uses the C<||logical operator, and the
-second uses C<or>, which has lower precedence. Using C<||in the latter
+The first set of examples use the C<||logical operator, and the second
+set uses C<or>, which has lower precedence. Using C<||in the latter
examples would effectively mean
- open INF, ( "< datafile" || die "can't open datafile: $!" );
+ open my $info, "<", ( "datafile" || die "can't open datafile: $!" );
which is definitely not what you want.
-The other important thing to notice is that, just as in the shell,
-any whitespace before or after the filename is ignored. This is good,
-because you wouldn't want these to do different things:
+For accessing files with naughty names, see L<"Dispelling the Dweomer">.
- open INF, "<datafile"
- open INF, "< datafile"
- open INF, "< datafile"
+For backward compability with Perls before 5.6 there is also a 2-argument
+version of C<open>, which requires you attach the special redirection
+characters to the beginning of the thing to be opened:
-Ignoring surrounding whitespace also helps for when you read a filename
-in from a different file, and forget to trim it before opening:
+ open( my $info, ">$datafile" ) || die "Can't create $datafile: $!";
+ open( my $info, "<$datafile" ) || die "Can't open $datafile: $!";
+ open( my $info, "$inputfile" ) || die "Can't open $inputfile: $!";
- $filename = <INF>; # oops, \n still there
- open(EXTRA, "< $filename") || die "can't open $filename: $!";
+Note, in this version the leading less-than is optional, but it is not
+recommended to leave it out. If omitted, Perl normally assumes that you
+want to open the file for reading.
-This is not a bug, but a feature. Because C<openmimics the shell in
-its style of using redirection arrows to specify how to open the file, it
-also does so with respect to extra whitespace around the filename itself
-as well. For accessing files with naughty names, see
-L<"Dispelling the Dweomer">.
+ the other hand if the value of $inputfile was received from an external
+source and if for some reason the name given includes a leading grater-than
+sign then the file will be opened for writing. Certainly not what you wanted.
+Leaving out the leading less-than sign can create a security hole in your code.
-There is also a 3-argument version of C<open>, which lets you put the
-special redirection characters into their own argument:
+In addition for backward compability with Perl before 5.6.0, one can
+use bare words as filehandles:
- open( INF, ">", $datafile ) || die "Can't create $datafile: $!";
+ open( INF, ">$datafile" ) || die "Can't create $datafile: $!";
+
+This is not a recommended practice any more as it has several drawbacks
+such as being INF being global to the whole application and being
+very hard to pass as argument to a function.
-In this case, the filename to open is the actual string in C<$datafile>,
-so you don't have to worry about C<$datafilecontaining characters
-that might influence the open mode, or whitespace at the beginning of
-the filename that would be absorbed in the 2-argument version. Also,
-any reduction of unnecessary string interpolation is a good thing.
=head2 Indirect Filehandles