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

Hi Monks,

I am reading a file and then doing some regex updates on the buffer and then writing it out.

Seems simple enough, but I get some parts of the buffer at the end of the file (ie see some stuff twice). After much searching I found a post on the net with the exact error, but no fix...they did mention concern about using "+<" in the open, which I do...I have also tried sysread, no diff.

If I just print to STDOUT it ALWAYS looks correct...

Here is the skelton: (I am on Win32)
use Fcntl qw(:DEFAULT :flock); if (open(FILE, "+< stuff.txt")) #if (sysopen(FILE, "stuff.txt", O_RDWR)) { # if (flock(FILE, LOCK_EX|LOCK_NB)) { local $/ = undef; my $buff = <FILE>; # my $buff = ''; # sysread(FILE, $buff, -s FILE); # DO STUFF TO $buff HERE, can GROW or SHRINK # Split it into pieces... seek(FILE, 0, 0); print FILE, $top_of_buffer; print FILE, $new_stuff; print FILE, $bot_of_buffer; close(FILE);

Replies are listed 'Best First'.
Re: file updating question
by Thelonius (Priest) on Nov 28, 2002 at 02:14 UTC
    That's not what you want to do. If you write over the file with something smaller, you will still have old stuff left over at the end. What you should do is write to a NEW file and then move the new file over the old file. You can use "perl -i". See "perldoc perlrun" for details.
      Thanks for the pointer, didn't know this stuff. Assuming it is OK to grow the file, how about this??? (It works for my testing...)
      if (open(FILE, "+< stuff.txt")) { local $/ = undef; my $buff = <FILE>; truncate(FILE, 0); # Update $buff print FILE $buff;
Re: file updating question
by pg (Canon) on Nov 28, 2002 at 02:12 UTC
    There is one error in your code: in your print statement, there should be no comma after file handler.

    Also, if the new content you write out is a "shrinked version" of the old content, for sure, you will see some of the old content at the end of your file. The write is a kind of "in-place" overwrite, whatever not being overwritten from the old content will remain there. Don't expect it will clean up the file first, and then write out. Especially if your file record is variable-length, you will see broken records.

    You can also read perlrun document for other approaches, and read that big chuck under -i option.

Re: file updating question
by rbc (Curate) on Nov 28, 2002 at 05:00 UTC
    If I just print to STDOUT it ALWAYS looks correct
    Then why not just print to STDOUT?

    You may just want to simplify your script.
    ... while(<>) { # do stuff print $whatever; }
    Then you could simply run the script like so ...
    $ myscript < inputfile > outputfile