Reputation: 167
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
Reputation: 1675
You chomp
$username
, but not $line
, so $username
will never equal $line
.
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.
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
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