Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

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
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.


    "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>.

        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?

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2024-06-15 17:57 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.