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

open FH, ">>$output_file"; "Opens a file for appending. When you start writing to this file, it will write to the end. "

O.K. but how to append a file to the begining?

open (GB,"+<$bookfile")||die "can't open\n";\n seek (GB,0,0); print GB "$data1|$data2|\n";

works but always the first line is deleted. How to write a file at the begining and preserve all data? sOKOle

Replies are listed 'Best First'.
Re: begining of a file
by chipmunk (Parson) on Aug 21, 2001 at 17:47 UTC
      open (FILE,"<file") || die "Could not open file : $!\n"; @contents = <FILE>; $head = shift(@contents); close(FILE); $new_entry = 'Welcome to www.perlmonks.org'; open (FILE, ">file") || die "Could not open file : $!\n"; unshift (@contents,$head,$new_entry); print FILE "@contents\n"; close(FILE);
      Can be simplified, but it works....
Re: begining of a file
by busunsl (Vicar) on Aug 21, 2001 at 17:07 UTC
    You cannot append something at the beginning of a file.

    Try something like this:

    open a temportary file
    write something into it
    open the old file
    read the contents
    write it to the temporary file
    close both files
    rename the temporary

Re: begining of a file
by Hofmator (Curate) on Aug 21, 2001 at 17:14 UTC

    You can't write to the beginning of a file. This is a problem which comes due to the nature of (most) file systems. Think of a file as a pile of books, it's very easy to put books on top (at the end) of it but it's not possible to put books under (at the start of) it (at least if it's very high :)

    So you have to work around that problem, there are two ways to do it

    1. Open the file for read/write (as in your 2nd example). Read in the whole file. Then seek to 0. Print your first line(s) to it. Then print the rest of the file back.
    2. The problem of this is that it's not good to read in the whole file into memory (especially if it's big). So create a temporary file. Write your first lines into it, read your original file into memory but only a reasonable amount at a time (e.g. a line, 1K, 32K, ...) and write that at once out to the temp file. At the end you have to copy the temp file onto the original one (and maybe leave a backup of it somewhere).

    -- Hofmator

Re: begining of a file
by joefission (Monk) on Aug 21, 2001 at 17:13 UTC
    Depends on how big and what format you require.

    One way is to put the contents of the file into an array, write your first line(s), then spit the array afterward. Example (yeah I'm skipping strict, warnings, errorcodes, and other good programming practices):

    open (GB,"$bookfile"); @oldstuff = <GB>; close GB; open (FILE,">$newfile"); print FILE "pre-pendings here\n"; print FILE "@oldstuff"; close FILE; # rename file if necessary

    Another way is to write your pre-pending content to a file, then stream (is this the right word) the old file contents. In other words:

    open (FILE,">$newfile"); print FILE "pre-pendings here\n"; open (GB,"$bookfile"); while (<GB>) { print FILE "$_"; } close GB; close FILE; # rename file if necessary
      Yet another way is to cheese together a tied filehandle that simply prepends whatever you write onto the beginning of the file. Kinda like what you're doing, but with a simpler interface.
      package Beginning; use Fcntl; sub TIEHANDLE { my($class)=@_; return bless { fh=> undef }, $class; } sub OPEN { my($self)=shift; return sysopen($self->{fh}, $_[0], O_RDWR | O_CREAT, 0666); } sub CLOSE { close($_[0]->{fh}) if ($_[0]->{fh}); $_[0]->{fh}=undef; } sub PRINT { my($self,$len)=shift; local $/; $_=$self->{fh}; seek $_, 0, 0 or warn "$!"; my $buf=<$_>; seek $_, 0, 0 or warn "$!"; print $_ @_; print $_ $buf; }
      Then to use it just:
      tie *FH, "Beginning"; open(FH, "Hello"); # This will actually be read/write print FH "Look ma, I'm first", scalar(localtime), "\n"; close(FH);
      It's incomplete and not scalable, just something to think about. A fun modification might be to have the PRINT callback "shuffle" the blocks of the file forward with each write. This would save wear-and-tear on $buf (but not your disk!).
Re: begining of a file
by sOKOle (Acolyte) on Aug 23, 2001 at 15:50 UTC
    Thank you my masters, I've followed Hoffmator's b advice. Everything works. sOKOle