X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/7a98bd7582df3d286ae2c6a25d16bdea7325962a..e76f5e873f85fc85f1c899914749a50feed6f801:/pod/perlfaq5.pod diff --git a/pod/perlfaq5.pod b/pod/perlfaq5.pod index 8ae3086..76b6d3e 100644 --- a/pod/perlfaq5.pod +++ b/pod/perlfaq5.pod @@ -448,12 +448,12 @@ temporary files in one process, use a counter: my $base_name = sprintf "%s/%d-%d-0000", $temp_dir, $$, time; sub temp_file { - local *FH; + my $fh; my $count = 0; - until( defined(fileno(FH)) || $count++ > 100 ) { + until( defined(fileno($fh)) || $count++ > 100 ) { $base_name =~ s/-(\d+)$/"-" . (1 + $1)/e; # O_EXCL is required for security reasons. - sysopen my($fh), $base_name, O_WRONLY|O_EXCL|O_CREAT; + sysopen $fh, $base_name, O_WRONLY|O_EXCL|O_CREAT; } if( defined fileno($fh) ) { @@ -494,8 +494,8 @@ Berkeley-style ps: } We've used a hash slice in order to easily handle the fields of each row. -Storing the keys in an array means it's easy to operate on them as a -group or loop over them with for. It also avoids polluting the program +Storing the keys in an array makes it easy to operate on them as a +group or loop over them with C. It also avoids polluting the program with global variables and using symbolic references. =head2 How can I make a filehandle local to a subroutine? How do I pass filehandles between subroutines? How do I make an array of filehandles? @@ -542,7 +542,7 @@ check out the Symbol or IO::Handle modules. =head2 How can I use a filehandle indirectly? X -An indirect filehandle is using something other than a symbol +An indirect filehandle is the use of something other than a symbol in a place that a filehandle is expected. Here are ways to get indirect filehandles: @@ -553,8 +553,7 @@ to get indirect filehandles: $fh = *SOME_FH{IO}; # blessed IO::Handle from *SOME_FH typeglob Or, you can use the C method from one of the IO::* modules to -create an anonymous filehandle, store that in a scalar variable, -and use it as though it were a normal filehandle. +create an anonymous filehandle and store that in a scalar variable. use IO::Handle; # 5.004 or higher my $fh = IO::Handle->new(); @@ -646,21 +645,21 @@ X (contributed by brian d foy) -If you want to C into a string, you just have to a +If you want to C into a string, you just have to a filehandle to a string, which Perl has been able to do since Perl 5.6: open FH, '>', \my $string; write( FH ); - + Since you want to be a good programmer, you probably want to use a lexical filehandle, even though formats are designed to work with bareword filehandles -since the default format names take the filehandle name. However, you can +since the default format names take the filehandle name. However, you can control this with some Perl special per-filehandle variables: C<$^>, which names the top-of-page format, and C<$~> which shows the line format. You have to change the default filehandle to set these variables: open my($fh), '>', \my $string; - + { # set per-filehandle variables my $old_fh = select( $fh ); $~ = 'ANIMAL'; @@ -671,24 +670,24 @@ to change the default filehandle to set these variables: format ANIMAL_TOP = ID Type Name . - + format ANIMAL = @## @<<< @<<<<<<<<<<<<<< $id, $type, $name . Although write can work with lexical or package variables, whatever variables -you use have to scope in the format. That most likely means you'll want to +you use have to scope in the format. That most likely means you'll want to localize some package variables: { local( $id, $type, $name ) = qw( 12 cat Buster ); write( $fh ); } - + print $string; -There are also some tricks that you can play with C and the +There are also some tricks that you can play with C and the accumulator variable C<$^A>, but you lose a lot of the value of formats since C won't handle paging and so on. You end up reimplementing formats when you use them. @@ -843,7 +842,7 @@ be an atomic operation over NFS. That is, two processes might both successfully create or unlink the same file! Therefore O_EXCL isn't as exclusive as you might wish. -See also the new L. +See also L. =head2 Why do I sometimes get an "Argument list too long" when I use E*E? X @@ -873,13 +872,13 @@ X (contributed by Brian McCauley) -The special two argument form of Perl's open() function ignores +The special two-argument form of Perl's open() function ignores trailing blanks in filenames and infers the mode from certain leading characters (or a trailing "|"). In older versions of Perl this was the only version of open() and so it is prevalent in old code and books. -Unless you have a particular reason to use the two argument form you -should use the three argument form of open() which does not treat any +Unless you have a particular reason to use the two-argument form you +should use the three-argument form of open() which does not treat any characters in the filename as special. open my $fh, "<", " file "; # filename is " file " @@ -998,7 +997,7 @@ X X If you are on a system that correctly implements C and you use the example appending code from "perldoc -f flock" everything will be OK even if the OS you are on doesn't implement append mode correctly -(if such a system exists.) So if you are happy to restrict yourself to +(if such a system exists). So if you are happy to restrict yourself to OSs that implement C (and that's not really much of a restriction) then that is what you should do. @@ -1017,7 +1016,7 @@ C function which is simply a wrapper around your system's C system call. There is still a small theoretical chance that a signal will interrupt -the system level C operation before completion. There is also +the system-level C operation before completion. There is also a possibility that some STDIO implementations may call multiple system level Cs even if the buffer was empty to start. There may be some systems where this probability is reduced to zero, and this is @@ -1119,26 +1118,6 @@ to each filehandle. =head2 How can I read in an entire file all at once? X X -Are you sure you want to read the entire file and store it in memory? -If you mmap the file, you can virtually load the entire file into a -string without actually storing it in memory: - - use File::Map qw(map_file); - - map_file my $string, $filename; - -Once mapped, you can treat C<$string> as you would any other string. -Since you don't necessarily have to load the data, mmap-ing can be -very fast and may not increase your memory footprint. - -If you want to load the entire file, you can use the C -module to do it in one one simple and efficient step: - - use File::Slurp; - - my $all_of_it = read_file($filename); # entire file in scalar - my @all_lines = read_file($filename); # one line per element - The customary Perl approach for processing all the lines in a file is to do so one line at a time: @@ -1157,13 +1136,35 @@ you see someone do this: my @lines = ; You should think long and hard about why you need everything loaded at -once. It's just not a scalable solution. You might also find it more +once. It's just not a scalable solution. + +If you "mmap" the file with the File::Map module from +CPAN, you can virtually load the entire file into a +string without actually storing it in memory: + + use File::Map qw(map_file); + + map_file my $string, $filename; + +Once mapped, you can treat C<$string> as you would any other string. +Since you don't necessarily have to load the data, mmap-ing can be +very fast and may not increase your memory footprint. + +You might also find it more fun to use the standard C module, or the C module's C<$DB_RECNO> bindings, which allow you to tie an array to a file so that -accessing an element the array actually accesses the corresponding +accessing an element of the array actually accesses the corresponding line in the file. -You can read the entire filehandle contents into a scalar. +If you want to load the entire file, you can use the C +module to do it in one one simple and efficient step: + + use File::Slurp; + + my $all_of_it = read_file($filename); # entire file in scalar + my @all_lines = read_file($filename); # one line per element + +Or you can read the entire file contents into a scalar like this: my $var; { @@ -1177,8 +1178,7 @@ close the file at block exit. If the file is already open, just use this: my $var = do { local $/; <$fh> }; -You can do that one better by using a localized C<@ARGV> so you can -eliminate the C: +You can also use a localized C<@ARGV> to eliminate the C: my $var = do { local( @ARGV, $/ ) = $file; <> }; @@ -1186,7 +1186,7 @@ For ordinary files you can also use the C function. read( $fh, $var, -s $fh ); -That third argument tests the byte size of the data on the C filehandle +That third argument tests the byte size of the data on the C<$fh> filehandle and reads that many bytes into the buffer C<$var>. =head2 How can I read in a file by paragraphs? @@ -1281,7 +1281,7 @@ not POSIX, not Unix, etc.) systems. You should also check out the Frequently Asked Questions list in comp.unix.* for things like this: the answer is essentially the same. -It's very system dependent. Here's one solution that works on BSD +It's very system-dependent. Here's one solution that works on BSD systems: sub key_ready { @@ -1320,7 +1320,7 @@ Or write a small C program using the editor of champions: % ./fionread 0x4004667f -And then hard code it, leaving porting as an exercise to your successor. +And then hard-code it, leaving porting as an exercise to your successor. $FIONREAD = 0x4004667f; # XXX: opsys dependent @@ -1373,7 +1373,7 @@ Or even with a literal numeric descriptor: my $fd = $ENV{MHCONTEXTFD}; open $mhcontext, "<&=$fd"; # like fdopen(3S) -Note that "<&STDIN" makes a copy, but "<&=STDIN" make +Note that "<&STDIN" makes a copy, but "<&=STDIN" makes an alias. That means if you close an aliased handle, all aliases become inaccessible. This is not true with a copied one.