Search code examples
fileperl

I open a file in write multiple times, but looks like the different writes stack on each other


I'm writing a code in Perl that modify a configuration file and launches a program that uses all this 4 times. But, the part that modify the file has a problem. I open the file in write mode (">"), and for the first edit, it is all ok, but then the other writes are stacked as if the file is open in append mode (">>").

#!/usr/bin/perl

$conf_file = "Configuration.txt";
$times_file = "tempi.txt";

sub cambiaNThreads {
    $numero = shift;

    @file_aggiornato;

    open $in, '<', $conf_file or die "Impossibile leggere il file $conf_file: $!";

    while( <$in> )
    {
        if ($_ =~ /number_node_/) 
        {
            $_ =~ s/:\s*\K\d+/$numero/;
        }

        push @file_aggiornato, $_;
    }

    close($in) or die "Impossibile chiudere il file '$conf_file': $!";

    open my $out, '>', $conf_file or die "Impossibile scrivere sul file $conf_file: $!";

    foreach (@file_aggiornato) {
        print $out $_;
    }

    close($out) or die "Impossibile chiudere il file '$conf_file': $!";   
}

open my $out, '>>', $times_file or die "Impossibile scrivere sul file $out: $!";

for (1..4) {
    $n_th = $_ ** 2;
    cambiaNThreads($n_th);

    print $out "\n =============$n_th=============";
    print $out qx(make pthreads_cond_o3_noout);
}

close($out) or die "Impossibile chiudere il file '$out': $!";

This is the configuration file after a run:

number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 1
number_node_y: 1
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 4
number_node_y: 4
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 9
number_node_y: 9
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 9
number_node_y: 9
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 16
number_node_y: 16
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 16
number_node_y: 16
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 16
number_node_y: 16
number_steps: 300
output_file_name: ballout
number_of_columns: 400
number_of_rows: 100
border_size_x: 1
border_size_y: 1
number_borders: 2
number_node_x: 16
number_node_y: 16
number_steps: 300
output_file_name: ballout

Solution

  • Change:

    @file_aggiornato;
    

    to:

    my @file_aggiornato;
    

    The problem is that the @file_aggiornato array is a global variable, but you expected it to be a local variable. The way to make it local to the scope of your sub is to declare it with my.

    Your code calls the sub 4 times. The 1st time it is called, it adds all lines of the config input file to the array. Then it overwrites the config file with the contents of the array, leaving the config file with the same number of lines it originally had.

    The 2nd time the sub is called, it appends all lines of the config input file to the array, doubling the size of the array. Then it overwrites the config file again with the contents of the array, leaving the config file with double the number of lines it originally had. And so on.

    You should add use warnings; to your code because it lets you know about potential bugs in your code like this. It would have given you a warning like:

    Useless use of a variable in void context at line ...
    

    pointing to your line:

    @file_aggiornato;
    

    You should also add use strict; and declare all your variables with my. This can also catch potential bugs.