R00059159
R00059159

Reputation: 167

Overwriting a file in perl

How would I go about overwriting a file with an array using Perl?

My file looks like this:

username1
comment
comment
comment
username2
comment
comment
username3
comment
comment
comment
...

What I do is load the lines into an array first. Then go through the array adding lines to a new array. When it finds the line of the user I want to add the comment to it will trigger a flag that makes it add the comment on the next incrementation of the loop. Then after that it just adds the rest of the lines to the array. What I want to do then it use the new array to overwrite the file. That is where I am stuck.

sub AddComment() {

  my $username = shift;    # the username to find
  my $comment  = shift;    # the comment to add
  chomp($comment);
  chomp($username);

  open my $COMMENTS, '<', "comments.txt" or die "$!";    #open the comments file
  my @lines = <$COMMENTS>;              #Make an array of the files lines

  my @NewCommentsFile;                  # make an array to store new file lines
  my $addCommentNow = 0;                # flag to know when to add comment

  for my $line (@lines) {
    if ($line eq $username) {           # if this line is the username
      $addCommentNow = 1;               # set flag that next line you add comment
      push(@NewCommentsFile, $line);    # add this line to new array
    }
    elsif ($addCommentNow eq 1) {       # if the flag is 1 then do this
      push(@NewCommentsFile, $comment); # add the comment to the array
      $addCommentNow = 0;               # reset flag
    }
    else {
      push(@NewCommentsFile, $line);       #add line to array
    }
  }

  open my $fh, '>', "comments.txt" or die "Cannot open output.txt: $!";

  # Loop over the array
  foreach (@NewCommentsFile) {
    print $fh "$_";    # Print each entry in our new array to the file
  }

  close $fh;
}

Upvotes: 1

Views: 9330

Answers (2)

codnodder
codnodder

Reputation: 1675

  1. You chomp $username, but not $line, so $username will never equal $line.

  2. You chomp the new comment to be added, but in your final loop you are printing without a newline. So, any new comment that you print would be file prepended onto whatever line follows it.

  3. Your elsif ($addCommentNow eq 1) { will throw away the current buffer or do other odd things depending on the input.

Try this modified code (that only addresses those three concerns):

for my $line (@lines) {
    chomp $line;
    push(@NewCommentsFile, $line);
    push(@NewCommentsFile, $comment) if $line eq $username;
}
open my $fh, '>', "comments.txt" or die "Cannot open output.txt: $!";
foreach (@NewCommentsFile) {
    print $fh "$_\n"; # Print each entry in our new array to the file
}
close($fh);

Upvotes: 5

Igor Chubin
Igor Chubin

Reputation: 64613

Don't open the file two times. Just use seek to go to the beginning of it:

seek($COMMENTS, 0, 0);

And, of course, open it for read/write (use "+<").

Upvotes: 2

Related Questions