Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

slurp mode

by szabgab (Priest)
on Nov 01, 2005 at 17:12 UTC ( [id://504656]=perlmeditation: print w/replies, xml ) Need Help??

If I am not mistaken this is the standard way to slurp in the content of a file is this:
sub slurp { local $/ = undef; open my $fh, $_[0] or die "Can't open $_[0]: $!"; my $slurp = <$fh>; return $slurp; } my $content = slurp($file)
I wonder why isn't this code used, or used more often?
open my $fh, $file or die "Can't open $file: $!"; my $content = join "", <$fh>; close $fh; # or just let it close by the next }
Am I missing here some serious thing?

Replies are listed 'Best First'.
Re: slurp mode
by xdg (Monsignor) on Nov 01, 2005 at 17:30 UTC

    Joining every line is less efficient, as you wind up searching for newlines to break into lines, allocating an array, filling it, joining it and assigning to a scalar.

    The standard approach turns off the newline searching and just reads it to a scalar in a single shot.

    See the discussion in the documentation for File::Slurp.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: slurp mode
by radiantmatrix (Parson) on Nov 01, 2005 at 20:03 UTC

    The reason your second block of code isn't used more is because it is much slower. On small amounts of data, you won't notice, but on larger ones you will. Why?

    In the top block of code, perl knows to just read, as fast as reasonable, the entire contents of a file and store it to a variable.

    In the lower block of code, it must read one line at a time (which takes longer, partly because there must be a check for line endings). Then, it must join those lines into a string before returning. That's a lot of extra steps.

    Actually, your "standard" way of slurping is less than ideal as well, since you are copying the string when your function returns. Why not:

    my $content; { local $/ = undef; open my $fh, $_[0] or die "Can't open $_[0]: $!"; $content = <$fh>; }

    Or, if it really must be abstracted into a sub, pass around a reference?

    sub slurp { local $/ = undef; open my $fh, $_[0] or die "Can't open $_[0]: $!"; my $slurp = <$fh>; return \$slurp; } my $content = slurp('filename'); print $$content;

    Of course, you could avoid all this re-inventing of the wheel and just use Slurp:

    use Slurp; my $content = slurp('filename');
    <-radiant.matrix->
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    "In any sufficiently large group of people, most are idiots" - Kaa's Law
Re: slurp mode
by duff (Parson) on Nov 01, 2005 at 17:46 UTC

    I don't know if your way is "standard" or not, but I've done it like so on occasion:

    my $content = do { local(@ARGV,$/) = $filename; <> };
    (when I've just wanted the program to die with an appropriate error when it can't open the file)

    Anyway, why go through all the trouble of reading line by line and joining all of the lines together when you can just read the entire file into a scalar without all of the extra processing?

Re: slurp mode
by Aristotle (Chancellor) on Nov 01, 2005 at 20:37 UTC

    Don’t use two-argument open. It’s dangerous.

    And if you do, at least don’t omit the mode as well. That’s doubly dangerous.

    Otherwise, there is opportunity for someone to do mischief, should any user input ever get close to your $filename. Stay away. Be explicit. Use three-argument open and always fasten your seatbelt.

    As far as slurping is concerned, as others have mentioned, you want to explicitly undefine $/, so that Perl won’t waste effort splitting the input into lines, only to then waste more effort gluing them back together. I tend to do this using a do {} block, much like those which tinita posted, because I rarely need to slurp files in more than one place in my code.

    Makeshifts last the longest.

Re: slurp mode
by robin (Chaplain) on Nov 01, 2005 at 18:23 UTC
    There's a pretty comprehensive discussion of file slurping back at this old thread.
Re: slurp mode
by gaal (Parson) on Nov 03, 2005 at 14:30 UTC
Re: slurp mode
by blahblah (Friar) on Nov 04, 2005 at 21:52 UTC
    My favorite slurp thread is Slurp a file. I like the benchmarks there.
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://504656]
Approved by kirbyk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2024-04-20 02:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found