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

Hi Venerable Monks,

A couple of days ago I posted a question which involved use of a seek function so as to write out lines from the position specified by seek. I was given some really helpful procedural suggestions, HOWEVER, the question is actually for an online class, which asks to do it via the function. My dilemma is that I don't think it works for writing out to files.

Can any of you let me know that either it does not work -or- it does? And if it does, what am I missing?

For example:
File cat.txt
cat
in
the
hat

#!/usr/bin/perl -w open (TEST,">>cat.txt"); seek (TEST,0,0); print "The\n"; close (TEST);


Should I get:
File cat.txt
The
cat
in
the
hat

If I shouldn't, what need I do (if relying on using seek) to do so?

Oh, and I also tried open (TEST,"+>>cat.txt");

Thanks In Advance,

o2

Replies are listed 'Best First'.
Re: Using seek function to write out to top of file?
by Fletch (Bishop) on May 26, 2005 at 17:11 UTC

    No, you'll get "The\nin\nthe\nhat\n". A file is an ordered sequence of octets. There's no way for seek to magically shift the previous contents down when you start writing at the beginning. See perldoc -q "append to the beginning" for more details.

    --
    We're looking for people in ATL

      Hi,

      Oh, tlm, I did not try your method, but (time permitting), I will give it a shot. I tried the following 8 cases.

      File t.txt:
      cat
      in
      the
      hat

      Case 1 (write,no + sign, use seek):
      #!/usr/bin perl -w open (TEST,">t.txt); seek (TEST,0,0); print TEST "The\n"; close (TEST);


      Case 2 (write, + sign, use seek):
      #!/usr/bin perl -w open (TEST,"+>t.txt); seek (TEST,0,0); print TEST "The\n"; close (TEST);


      Case 3 (append, no plus sign, use seek):
      #!/usr/bin perl -w open (TEST,">>t.txt); seek (TEST,0,0); print TEST "The\n"; close (TEST);


      Case 4 (append, use + sign, use seek):
      #!/usr/bin perl -w open (TEST,"+>>t.txt); seek (TEST,0,0); print TEST "The\n"; close (TEST);


      Case 5 (write, no plus sign, use sysseek):
      #!/usr/bin perl -w open (TEST,">t.txt); sysseek (TEST,0,0); syswrite TEST, "The\n"; close (TEST);


      Case 6 (write, use + sign, use sysseek):
      #!/usr/bin perl -w open (TEST,"+>t.txt); sysseek (TEST,0,0); syswrite TEST, "The\n"; close (TEST);


      <Case 7 (append, no + sign, use sysseek):
      #!/usr/bin perl -w open (TEST,">>t.txt); sysseek (TEST,0,0); syswrite TEST, "The\n"; close (TEST);


      Case 8 (append, use + sign, use sysseek):
      #!/usr/bin perl -w open (TEST,"+>>t.txt); sysseek (TEST,0,0); syswrite TEST, "The\n"; close (TEST);


      Results:
      Cases 1,2,5,6
      t.txt
      The

      Cases 3,4,7,8:
      t.txt
      cat
      in
      the
      hat
      The

      Conclusion:
      The results are driven by one thing; whether opening the file to write (>) or to append (>>). Using + doesn't do anything and using sysseek gives the same result as seek. Whether going to the beginning of the file with seek or with sysseek (and using append), writing was performed AT THE END OF THE FILE.

      I'm kind of surprised. The responses I got had the expectation that writing would be done at the top of the file. I have never seen this to be the case.

      One quick question. Does opening to write (one > sign) ALWAYS cause the file to be emptied? This is what I have seen. I have never seen it have previous text.

      A reminder. This was for an on-line class, which requested this procedure. I find the class documentation to have had three mistakes (for which I am disappointed).

      1. It assumed that opening with write (not append) might leave previous text.

      2. It assumed you could write out at the top of a file (that has text in it from previously) using syseek at 0,0.

      3. It also used flock on explicit file name and not filehandle.

      Thanks, monks, for your assistance.

      o2

        You need to read perldoc -f open and perldoc perlopentut as it explains all of this. Opening with any form of > clobbers the output, and any form of >> opens in append mode. If you want to update in place you need to use +<.

        --
        We're looking for people in ATL

Re: Using seek function to write out to top of file?
by tlm (Prior) on May 26, 2005 at 17:12 UTC

    seek is not the tool I would choose for this task, but if I had to use it, I'd do this:

    open my $fh, '+<cat.txt' or die $!; my $text = do { local $/; <$fh> }; # slurp die "seek failed\n" unless seek( $fh, 0, SEEK_SET ); print $fh "The\n$text"; close $fh;
    If one seeks and then just writes "The\n", some of the original contents of the file will get overwritten. Therefore one has to first save these contents, and write them back out. See seek.

    Updates: fixed typo: s/<\+/+</ ; added check on seek's success; replaced 0 with SEEK_SET as the third argument of seek.

    the lowliest monk

Re: Using seek function to write out to top of file?
by revdiablo (Prior) on May 26, 2005 at 17:39 UTC

    As others have stated, seek will not do what you want here. You have to basically rewrite the whole file. Or you can use a module to do that for you, such as Tie::File. Check that one out, it might be just what you need.

Re: Using seek function to write out to top of file?
by zentara (Cardinal) on May 26, 2005 at 19:02 UTC
    It's rewriting the file, but it works.
    #!/usr/bin/perl -w #also see IO-Sendfile use strict; use Fcntl ':seek'; #krahn #> I have a text file that i want to insert two lines to the top of. #> how do i do this? my $file = 'head-1testfile'; open FILE, "+< $file" or die "Cannot open $file: $!"; my @lines = <FILE>; seek FILE, 0, SEEK_SET or die "Cannot seek on $file: $!"; print FILE <<TEXT, @lines; This is the new line one. This is the new line two. TEXT

    I'm not really a human, but I play one on earth. flash japh