in reply to appending to a file

The ">" argument to open means "truncate existing file and open for output" or "open a new file for output", depending on if the file exists already or not. Note, that's a lot different from appending.

Append is ">>" (two >'s next to each other).

In other words, instead of this:

open FH, ">filename" or die "Bleah!\n$!";

File level appending is opened like this:

open FH, ">>filename" or die "Bleah!\n$!";

Have a look at perlopentut for details.

However, your code looks like it's trying to slurp in the file first, and then write it back out from scratch, while adding the new stuff at the end. Ok, that's one strategy, but it's not exactly the same thing as doing a file append.

As for your code, a better solution (since you also seem to be doing some processing on the current file, if it exists) would be this:

Open the input file. Open a temporary output file. Read the input file line by line. Process one line of input. Write it out to the output file. When done, append your additional information to the output file. Close the input file. Close the output file. Then rename your temp file so that it replaces your input file. Do your writing in standard ">" mode, because you're writing a new temp file, not appending to an existing file.


Dave

Replies are listed 'Best First'.
Re^2: appending to a file
by Anonymous Monk on Feb 26, 2004 at 06:46 UTC
    Open the input file. Open a temporary output file. Read the input file line by line. Process one line of input. Write it out to the output file. When done, append your additional information to the output file. Close the input file. Close the output file. Then rename your temp file so that it replaces your input file. Do your writing in standard ">" mode, because you're writing a new temp file, not appending to an existing file.

    This is quite the long-winded approach. Why would you want to have to read and then write back out each line, even ones that are not being modified? Too much file input/output! Take a look at my solution. It simply scans the file once over and appends the data (if necessary) at the very end. Simple yet efficient.

      This is quite the long-winded approach.

      Long winded, eh?

      perl -ni -e "BEGIN{ print qq/Enter new student's name:\n/; $name = <ST +DIN> } next if /^\Q$name\E\b/; print $_ . ( eof ) ? $name : q// " myt +est.doc

      Maybe you're right. ;)


      Dave

        I think IO::AtomicFile would come in handy here. :-)

        PS: I see by your quotes that you're a Windows user. You might want to provide a port of your oneliner that works with unix-like shells, or at least mention it.

        Considering that the code you just provided is not even close to what your guidelines were suggestion he do, you just cheated. A program following your guidelines would have looked like the following, which is long winded. And by long-winded, I don't mean code length, I mean that you're doing more work than is necessary (in this case, the overhead of unnecessary file output). Note that I didn't bother with file locking this time around.

        #!c:/perl/bin/perl -w $|++; use strict; print "Enter new student's name: "; chomp( my $student = <STDIN> ); open my $fh, '<', 'students.dat' or die "open failed: $!"; open my $tmp, '>', 'students.tmp' or die "open failed: $!"; my $found = 0; while (<$fh>) { print $tmp $_; $found = 1 if /^\Q$student\E$/i; } print $tmp $student, "\n" unless $found; close $fh; close $tmp; rename 'students.tmp', 'students.dat';
          A reply falls below the community's threshold of quality. You may see it by logging in.