17

Possible Duplicate:
What is the best way to slurp a file into a string in Perl?

Is this code a good way to read the contents of a file into a variable in Perl? It works, but I'm curious if there is a better practice I should be using.

open INPUT, "input.txt";
undef $/;
$content = <INPUT>;
close INPUT;
$/ = "\n";
Community
  • 1
  • 1
itzy
  • 11,275
  • 15
  • 63
  • 96
  • That isn't good code. This is better: `open(my $fh, "< :encoding(UTF-8)", "input.text") || die "can't open input.text: $!"; $content = do { local $/; <$fh> }; close($fh) || die "can't close input.text: $!";` – tchrist Nov 03 '10 at 15:25

3 Answers3

39

I think common practice is something like this:

    my $content;
    open(my $fh, '<', $filename) or die "cannot open file $filename";
    {
        local $/;
        $content = <$fh>;
    }
    close($fh);

Using 3 argument open is safer. Using file handle as variable is how it should be used in modern Perl and using local $/ restores initial value of $/ on block end, instead of your hardcoded \n.

n0rd
  • 11,850
  • 5
  • 35
  • 56
  • 1
    See http://search.cpan.org/dist/File-Slurp/extras/slurp_article.pod – Sinan Ünür Nov 03 '10 at 14:26
  • 1
    Can you please explain what is the purpose of `local $/`? It is not google friendly :) – Miroslav Popov Sep 17 '19 at 19:12
  • 1
    @MiroslavPopov, `$/` is the same as `$INPUT_RECORD_SEPARATOR`. [perlvar](https://perldoc.perl.org/perlvar.html) documentation covers it. Here specifically it enables the `$content = <$fh>` to read all file, not just its first line. – n0rd Sep 17 '19 at 19:19
  • @n0rd, tx. `local $/;` is actually `local $/ = undef;`, which cheats `` to read the complete file. Is it correct? (Perls is not .NET. We have to read the unwritten.) – Miroslav Popov Sep 17 '19 at 19:30
16
use File::Slurp;
my $content = read_file( 'input.txt' ) ;
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 6
    I disagree with loading a module merely to open and read a file. Being able to open and read files is too fundamental an operation not to understand very, very well. – tchrist Nov 03 '10 at 15:22
  • 20
    I disagree with endlessly writing the same five lines of code over and over when one plus a module will do. – Quentin Nov 03 '10 at 15:26
  • 7
    It's not even a standard module. This reduces the code’s portability. – tchrist Nov 03 '10 at 17:40
  • 6
    That's what dependancies in whatever you generate Makefiles from are for. – Quentin Nov 03 '10 at 17:59
3

Note that if you're in an environment where installing modules is possible, you may want to use IO::All:

use IO::All;
my $contents;
io('file.txt') > $contents;

Some of the possibilities get a bit crazy, but they can also be quite useful.

daxim
  • 39,270
  • 4
  • 65
  • 132
Daniel Martin
  • 23,083
  • 6
  • 50
  • 70
  • 1
    A non-standard module plus an tricksily overloaded `>` operator just to read a file, something every Perl programmer should be able to do in their sleep, seems like it’s going pretty far overboard. – tchrist Nov 03 '10 at 15:26
  • 1
    tchrist, overloading is not the problem, [conflating HTTP with local file access a la PHP's `readfile`](http://php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen) (we know how abysmal that turned out) is. But why the hating on CPAN modules? They are Perl's advantage, [it's foolish not to play it](http://stackoverflow.com/q/3700037#3700066). But even going so far to invent a combat term against them, that can't be good. – daxim Nov 03 '10 at 19:57