Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Slurp a file

by Anonymous Monk
on Jan 08, 2001 at 21:43 UTC ( [id://50525]=CUFP: print w/replies, xml ) Need Help??

Slurp a file into a scalar. Jean-Daniel Gamache webmaster@perls.org
open (IN, "<myfile.txt"); {local $/; $file_content = <IN>;} print $file_content;

Replies are listed 'Best First'.
Re: Slurp a file
by davorg (Chancellor) on Jan 08, 2001 at 21:53 UTC

    Oops. You've just left $/ set to undef for the rest of the program. This can lead to all sorts of nastiness.

    Better to do something like this:

    my $file_text; { local $/; $file_text = <FILE>; } print $file_text;

    Which returns $/ to its original value once you leave the bare block.

    Update: I should point out that my correction was to the original version of this node. It's now been changed to use my suggestion.

    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

        Tilly pointed me to the use of join in this case. Methinks it's pretty easy:
        $content = join '', <SOMEHANDLE>;
        Chipmunk, just 4u: One might see the actual response of tilly in this node <grin>.

        Jeroen
        I was dreaming of guitarnotes that would irritate an executive kind of guy (FZ)

Re: Slurp a file
by dkubb (Deacon) on Jan 15, 2001 at 13:46 UTC

    My favorite way of reading the contents of a filehandle into a scalar is:

    sysread FILEHANDLE, my $file_contents, -s FILEHANDLE;

    In benchmarks I've done this is the fastest and most elegant way that I've found.

      Modifying jeroenes's modification of davorg's modified benchmark (threw in tye's neat trick for good measure):
      Rate join argv hybrid linesep sysread join 5459/s -- -44% -71% -81% -91% argv 9690/s 78% -- -49% -67% -85% hybrid 19084/s 250% 97% -- -34% -70% linesep 29070/s 433% 200% 52% -- -55% sysread 64103/s 1074% 562% 236% 121% --

      Nice, dkubb! I think we have a winner. Not only is _sysread() clearly the fastest, but it burns the least CPU*. I like it! Hopefully there are no "catches."

      update: _argv() is almost as fast as _linesep() when working with large files. _join() and _hybrid() tend to fall behind.

      * Linux 2.4, Celeron-366, Perl 5.6.0


      #!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); my $file = $0; open(IN, $file) or die "$file: $!\n"; cmpthese(50_000, { join => \&_join, linesep => \&_linesep, hybrid => \&_hybrid, sysread => \&_sysread, argv => \&_argv }); close(IN); sub _join { seek(IN, 0, 0); my $content = join '', <IN>; } sub _linesep { seek(IN, 0, 0); my $content = do { local $/; <IN> } } sub _hybrid { seek(IN, 0, 0); my $content = do { local $/; join '', <IN> } } sub _sysread { seek(IN, 0, 0); sysread IN, my $content, -s IN } sub _argv { my $content = do { local(*ARGV, $/); @ARGV = ($file); <> } }

      Unfortunately, this isn't completely portable. There are minor (as far as I can tell) problems with some operating systems where the size of a file on disk doesn't always match the size of data read into memory.

      The big problems have to do with the great many types of filehandles where -s can't tell the file size.

      But, yes, when it works, this is a neat trick. Thanks.

              - tye (but my friends call me "Tye")
        Just a few questions:

        What types of filehandlers would not return the correct size with -s?

        And do you know a better way to get the size of a filehandle than using -s?

(tye)Re: Slurp a file
by tye (Sage) on Jan 08, 2001 at 21:56 UTC

    You need to check whether open fails and report a useful error. Here is a trick to do that for you:

    my $contents= do { local(*ARGV,$/); @ARGV="myfile.txt"; <> };
    Though I'm taking on faith that local(*ARGV) will properly save and restore everything that <> manipulates. (:

            - tye (but my friends call me "Tye")
Re: Slurp a file
by Anonymous Monk on Jan 08, 2001 at 22:54 UTC
    nope, the $\ is in a scope and retains it's original value.
Re: Slurp a file
by Anonymous Monk on Jan 08, 2001 at 22:57 UTC
    Sorry, you were right!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (2)
As of 2024-04-19 00:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found