Search code examples
perlfileioperl-io

What's the best way to open and read a file in Perl?


Please note - I am not looking for the "right" way to open/read a file, or the way I should open/read a file every single time. I am just interested to find out what way most people use, and maybe learn a few new methods at the same time :)*

A very common block of code in my Perl programs is opening a file and reading or writing to it. I have seen so many ways of doing this, and my style on performing this task has changed over the years a few times. I'm just wondering what the best (if there is a best way) method is to do this?

I used to open a file like this:

my $input_file = "/path/to/my/file";
open INPUT_FILE, "<$input_file"  || die "Can't open $input_file: $!\n";

But I think that has problems with error trapping.

Adding a parenthesis seems to fix the error trapping:

open (INPUT_FILE, "<$input_file")  || die "Can't open $input_file: $!\n";

I know you can also assign a filehandle to a variable, so instead of using "INPUT_FILE" like I did above, I could have used $input_filehandle - is that way better?

For reading a file, if it is small, is there anything wrong with globbing, like this?

my @array = <INPUT_FILE>;

or

my $file_contents = join( "\n", <INPUT_FILE> );

or should you always loop through, like this:

my @array;
while (<INPUT_FILE>) {
  push(@array, $_);
}

I know there are so many ways to accomplish things in perl, I'm just wondering if there are preferred/standard methods of opening and reading in a file?


Solution

  • There are no universal standards, but there are reasons to prefer one or another. My preferred form is this:

    open( my $input_fh, "<", $input_file ) || die "Can't open $input_file: $!";
    

    The reasons are:

    • You report errors immediately. (Replace "die" with "warn" if that's what you want.)
    • Your filehandle is now reference-counted, so once you're not using it it will be automatically closed. If you use the global name INPUT_FILEHANDLE, then you have to close the file manually or it will stay open until the program exits.
    • The read-mode indicator "<" is separated from the $input_file, increasing readability.

    The following is great if the file is small and you know you want all lines:

    my @lines = <$input_fh>;
    

    You can even do this, if you need to process all lines as a single string:

    my $text = join('', <$input_fh>);
    

    For long files you will want to iterate over lines with while, or use read.