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

Hi perlmonks, I need a help from you , I am trying to read and write(not append) a file concurrently using perl. I used the command open FILE,"+< file name" or die $!; and sysopen with O_RDWR option . the commands doing the correct thing , but what i need to is to write not append to the file . for example in file i have a word " hello how are you ". when i used the open or sysopen command with (print <handle> "fine how about you"; ) value "fine how about you " its appending the new value to the file. like " hi how are you fine how about you" . is there a way to write(not append) to a file while it was opened. there might be a way to do this , but i could not able to find that , please help me .
  • Comment on Read and write files concurrently in Perl

Replies are listed 'Best First'.
Re: Read and write files concurrently in Perl
by graff (Chancellor) on Jul 29, 2009 at 04:15 UTC
    If your plan is to replace the contents of the file at certain locations, then you'll be using seek, as suggested above by kyle.

    But in order for that to work as expected, you'll have to be careful to make sure that the replacement data you put in contains exactly the same number of bytes as the original data you are replacing in the file.

    For example, suppose you have a string like "foobar", starting at byte offset 20 in the file. If you seek to that offset and write "goober" (same number of bytes), that will "replace" the foobar string just fine. But if you seek to byte offset 20 and write something shorter, the last byte(s) of "foobar" will still be in file unchanged, and if you write something longer, whatever follows "foobar" will be overwritten as well.

    If your plan involves cases where the file should end up with a different byte count when you're done, you won't be able to do the editing "in place". You can try looking at Tie::File, although I'm not sure it does what you want in particular.

    If you want better help, try showing us a small amount of real data, together with some code that you've tried, and tell us what kind of result you really want, given that your code isn't producing that result.

Re: Read and write files concurrently in Perl
by GrandFather (Saint) on Jul 29, 2009 at 03:42 UTC

    Consider:

    use strict; use warnings; my $testFile = 'delme.txt'; unlink $testFile; open my $ioFile, '>', $testFile or die "Failed to open $testFile for u +pdate: $!\n"; print $ioFile "This is some output text\n"; my $seekBackPoint = tell $ioFile; print $ioFile "This line will get overwritten (at least partially)\n"; seek $ioFile, $seekBackPoint, 0; print $ioFile "Overwrite part of a line.\n"; close $ioFile; open my $iFile, '<', $testFile or die "Failed to open $testFile for re +ading: $!\n"; print <$iFile>; close $iFile;

    Prints:

    This is some output text Overwrite part of a line. ten (at least partially)

    Note: use lexical file handles and the three parameter version of open.


    True laziness is hard work
Re: Read and write files concurrently in Perl
by kyle (Abbot) on Jul 29, 2009 at 03:28 UTC

    I'm not sure from your description, but you may be looking for seek.

Re: Read and write files concurrently in Perl
by Anonymous Monk on Jul 29, 2009 at 02:36 UTC
    No. Files don't work like that.
    open INFILE ... open OUTFILE ... while(<INFILE>){ print OUTFILE ... } close INFILE close OUTFILE rename OUTFILE, INFILE
      Thanks Monk. But why it was desinged like this ? why we could not able to write to files while it was opened. if we are able to append , then we should able to write to a file right ? is there any dependency for this operation ? or do we have to unlink the handle while wrting to a file . i could not found much info from net regarding this ! . could you please help me to know this .
        Think of the file data on the disk as a sequential stream of bits (this is an approximation- but a good thought model here). Or perhaps a sequence of numbers: 123789, if we want the sequence 1234789, that means that the data 789 has to move down to make room! We have to carve a "hole" for the new "4" data and that is a complex thing to do. If say, the new "4" data is exactly the same size as the "7" data, and I mean *EXACTLY*, we could use seek() to move to that position and wind up with 123489 (replace 7 data with 4).

        Think of cassette tapes, if you record 3 songs and you want to add a new song at the beginning of the tape, you have to record the new song and then all of the next 3 songs over again. The disk works like that.

        Far and away your best bet if these files aren't huge, is to open the file for read, slurp it into a memory array, do what want to that data, open a new file for write, write the data, close the file and then delete the old file and rename the new file to the old file's name.

        Tie::File would do some grunt work for you, but this is what it essentially does and its not portable to Windows if that matters to you.

        To be frank, you are in way over your head if you intend to write something that can insert things into an existing file by yourself. That is definitely not beginner stuff!

        If the idea of reading the file into memory, working on it and writing it back out doesn't work, then this is time for using a Perl DB module or Tie::File.

        Anyway it works this way because the hardware works that way.

Re: Read and write files concurrently in Perl
by cdarke (Prior) on Jul 29, 2009 at 09:19 UTC
    I'm guessing that what you wish to do is insert a record into an existing file. The problem is that the open/read/print/close system works at the physical level, not the logical level. For many operations that is very efficient and just what you need, but on-the-fly inserts and deletes cannot be done with the file in situ. You need a database - that is (one reason) why they were invented.
Re: Read and write files concurrently in Perl
by Anonymous Monk on Jul 29, 2009 at 06:09 UTC

    Maybe I'm reading too much into your example text, but this kind of query("Hello, how are you?") / response("Fine. How about you?") system is better implemented with pipes or sockets