Search code examples
perlfilefile-io

How to read file in Perl and if it doesn't exist create it?


In Perl, I know this method :

open( my $in, "<", "inputs.txt" );

reads a file but it only does so if the file exists.

Doing the other way, the one with the +:

open( my $in, "+>", "inputs.txt" );

writes a file/truncates if it exists so I don't get the chance to read the file and store it in the program.

How do I read files in Perl considering if the file exists or not?

Okay, I've edited my code but still the file isn't being read. The problem is it doesn't enter the loop. Anything mischievous with my code?

open( my $in, "+>>", "inputs.txt" ) or die "Can't open inputs.txt : $!\n";
while (<$in>) {
    print "Here!";
    my @subjects    = ();
    my %information = ();
    $information{"name"}     = $_;
    $information{"studNum"}  = <$in>;
    $information{"cNum"}     = <$in>;
    $information{"emailAdd"} = <$in>;
    $information{"gwa"}      = <$in>;
    $information{"subjNum"}  = <$in>;
    for ( $i = 0; $i < $information{"subjNum"}; $i++ ) {
        my %subject = ();
        $subject{"courseNum"} = <$in>;
        $subject{"courseUnt"} = <$in>;
        $subject{"courseGrd"} = <$in>;
        push @subjects, \%subject;
    }
    $information{"subj"} = \@subjects;
    push @students, \%information;
}
print "FILE LOADED.\n";
close $in or die "Can't close inputs.txt : $!\n";

Solution

  • Use the proper test file operator:

    use strict;
    use warnings;
    use autodie;
    
    my $filename = 'inputs.txt';
    unless(-e $filename) {
        #Create the file if it doesn't exist
        open my $fc, ">", $filename;
        close $fc;
    }
    
    # Work with the file
    open my $fh, "<", $filename;
    while( my $line = <$fh> ) {
        #...
    }
    close $fh;
    

    But if the file is new (without contents), the while loop won't be processed. It's easier to read the file only if the test is fine:

    if(-e $filename) {
       # Work with the file
       open my $fh, "<", $filename;
       while( my $line = <$fh> ) {
          #...
       }
       close $fh;
    }