Thaodan
Thaodan

Reputation: 107

What produces the white space in my perl programm?

As the title says, I have a program or better two functions to read and write a file either in an array or to one. But now to the mean reason why I write this: when running my test several times my test program that tests my functions produces more and more white space. Is there somebody that could explain my fail and correct me?

my code

Helper.pm:

#!/usr/bin/env perl

package KconfCtl::Helper;


sub file_to_array($) {
    my $file = shift();
    my ( $filestream, $string );
    my @rray;

    open( $filestream, $file ) or die("cant open $file: $!");
    @rray = <$filestream>;
    close($filestream);
    return @rray;
 }


sub array_to_file($$;$) {
    my @rray = @{ shift() };
    my $file = shift();
    my $mode = shift();
    $mode='>' if not $mode;
    my $filestream;

    if ( not defined $file ) {
        $filestream = STDOUT;
    }
    else {
        open( $filestream, $mode, $file ) or die("cant open $file: $!");
     }
    my $l = @rray; print $l,"\n";
    foreach my $line (@rray) {
      print $filestream "$line\n";
    }
    close($filestream);
}



1;

test_helper.pl:

use KconfCtl::Helper;
use strict;
my @t;
@t= KconfCtl::Helper::file_to_array("kconf.test");
#print @t;
my $t_index=@t;
@t[$t_index]="n";
KconfCtl::Helper::array_to_file(\@t, "kconf.test", ">");

the result after the first:

n

and the 2nd run:

n

n

Upvotes: 1

Views: 153

Answers (2)

Borodin
Borodin

Reputation: 126742

When you read from a file, the data includes the newline characters at the end of each line. You're not stripping those off, but you are adding an additional newline when you output your data again. That means your file is gaining additional blank lines each time you read and write it

Also, you must always use strict and use warnings 'all' at the top of every Perl script; you should avoid using subroutine prototypes; and you should declare all of your variables as late as possible

Here's a more idiomatic version of your module code which removes the newlines on input using chomp. Note that you don't need the #! line on the module file as it won't be run from the command line, but you my want it on the program file. It's also more normal to export symbols from a module using the Exporter module so that you don't have to qualify the subroutine names by prefixing them with the full package name

use strict;
use warnings 'all';

package KconfCtl::Helper;

sub file_to_array {
    my ($file) = @_;

    open my $fh, '<', $file or die qq{Can't open "$file" for input: $!};  #'
    chomp(my @array = <$fh>);

    return @array;
 }

sub array_to_file {
    my ($array, $file, $mode) = @_;
    $mode //= '>';

    my $fh;
    if ( $file ) {
        open $fh, $mode, $file or die qq{Can't open "$file" for output: $!};  #'
    }
    else {
        $fh = \*STDOUT;
    }

    print $fh $_, "\n" for @$array;
}

1;

and your test program would be like this

#!/usr/bin/env perl

use strict;
use warnings 'all';

use KconfCtl::Helper;

use constant FILE => 'kconf.test';

my @t = KconfCtl::Helper::file_to_array(FILE);

push @t, 'n';

KconfCtl::Helper::array_to_file(\@t, FILE);

Upvotes: 5

AmbroseChapel
AmbroseChapel

Reputation: 12097

When you read in from your file, you need to chomp() the lines, or else the \n at the end of the line is included.

Try this and you'll see what's happening:

use Data::Dumper; ## add this line
sub file_to_array($) {
    my $file = shift();
    my ( $filestream, $string );
    my @rray;

    open( $filestream, '<', $file ) or die("cant open $file: $!");
    @rray = <$filestream>;
    close($filestream);
    print Dumper( \@rray ); ### add this line
    return @rray;
}

you can add

foreach(@rray){
  chomp();
}

into your module to stop this happening.

Upvotes: 3

Related Questions