Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

1. I want to maintain a flat file at 100 records (lines).
2. I want to add new records (lines) to the top of file.

My current code (hack) is adding spaces to the beginning of each line.

open (LOG,"log.dat"); @logfile = <LOG>; close(LOG); @old_logfile = @logfile[0..100]; open (LOG,">log.dat"); flock(LOG,2); print LOG "$date - $requesturi - ($httpuseragent) $remorehost: $remote +port ($remoteaddr) - $httpreferer\n"; print LOG "@old_logfile"; flock(LOG,8); close(LOG);
Thanks for any replies...
Liz

update (broquaint): title change (was How do I trauncate a flat file, then append to front?)

Replies are listed 'Best First'.
Re: How do I trauncate a flat file, then append to front?
by Zaxo (Archbishop) on Nov 16, 2002 at 05:21 UTC

    I'd unshift the new records onto @logfile and print the first hundred. What you have should work fine except for printing 102 records, one extra from off-by-one in 0..100, and the other from the added new record. Here goes:

    use Fcntl qw( :flock ); open (LOG, "+< /path/to/log.dat") or die $!; flock(LOG, LOCK_EX); my @logfile = <LOG>; unshift @logfile, "$date - $requesturi - ($httpuseragent)" . " $remorehost: $remoteport ($remoteaddr) -" . " $httpreferer\n"; seek LOG, 0, 0; print LOG @logfile[0..99] or die $!; close(LOG) or die $!;

    I used a single nontruncating open for read/write so that the lock holds through the read and write cycle. That's so another instance can't leap in with a record to be lost before you write.

    I also cleaned up some niceties, like checking for system errors and using Fcntl constants for locking.

    Is there some reason you don't want to simply append to the logfile? That would be more normal.

    After Compline,
    Zaxo

      The file needs to be read with newest at top.
      Also, I should've mentioned that i'm limited to perl 4.004
        Mind if I ask why you're limited to Perl 4.004? What's the OS? What kind of environment are you in, what do your computers do for you?
Re: How do I trauncate a flat file, then append to front?
by sauoq (Abbot) on Nov 16, 2002 at 06:08 UTC

    Use Tie::File. Try something like this:

    use Tie::File; $YOUR_LOG_LINE = "whatever you want.\n"; my @log; my $o = tie @log, 'Tie::File', 'log.dat' or die $!; $o->flock; # Default is conveniently LOCK_EX unshift @log, $YOUR_LOG_LINE; # Add line to beginning. $#log = 99 unless @log < 100; # Truncate to 100 lines if necessary.

    But, no. That won't work with perl4. Upgrade. Everyone's doing it. ;-)

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: How do I trauncate a flat file, then append to front?
by Anonymous Monk on Nov 16, 2002 at 05:23 UTC
    1) After you read in, do a chomp on each line;
    2)When you write out, do print LOG join("\n", @old_logfile)
    3) @old_logfile = @logfile[0 .. 100] is not safe, as you may have less than 100 lines at the beginning.
      For the third point, you can do:
      @old_logfile = @logfile[0..($#logfile > 99 ? 100 : $#logfile)];
      For point 1 and 2, you actually don't need to chomp the new lines away, and then add them back. Those blanks you got at the beginning of the lines, starting from the second line from the old file, is $LIST_SEPARATOR, and default value is space. You can do this:
      use English; $LIST_SEPARATOR = "";