Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 846
BrianH Avatar asked Nov 25 '08 20:11

BrianH


People also ask

How do I open a new file in Perl?

To create a file in Perl, you also use open(). The difference is that you need to prefix the file name with a > character to make Perl open the file for writing. Any existing file with the name you supply to open() will be overwritten, unless you specify >> instead, which opens a file for appending.


2 Answers

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.

like image 175
JSBձոգչ Avatar answered Oct 29 '22 19:10

JSBձոգչ


If you want the entire file as a single string, there's no need to iterate through it.

use strict; use warnings; use Carp; use English qw( -no_match_vars ); my $data = q{}; {    local $RS = undef; # This makes it just read the whole thing,    my $fh;    croak "Can't open $input_file: $!\n" if not open $fh, '<', $input_file;    $data = <$fh>;    croak 'Some Error During Close :/ ' if not close $fh; } 

The above satisfies perlcritic --brutal, which is a good way to test for 'best practices' :). $input_file is still undefined here, but the rest is kosher.

like image 32
Kent Fredric Avatar answered Oct 29 '22 17:10

Kent Fredric