If the part of the file you are going to be replacing is at the end, you can increase speed and efficiency by not writing to the disk until you get to the exact part of the file where you have made the change. Once you make a change, however, you'll have to write everything else from memory to the disk. This is basically because when you change a file, you change it's length. (If you are simply subsituting one letter for another, it's possible (though a bit foolhardy, IMO) to open it for read/write, find and make your changes, and close the file, as the size will remain the same) For a more normal, not-as-foolhardy case, use something like this:
This is kind of a pain (obviously) but really can save you memory if the file is large or your RAM is small. The above is also a bit verbose - you can remove a lot of the "$_" and "MYFILE"s from above - see the documentation on seek, truncate, and tell for more.## Open our file for reading and writing: open(MYFILE, "+< $myfile") or die "Could not open $myfile: $!\n"; ## File locking would be a Good Idea here ## Loop through the file one line at a time while(<MYFILE>) { if (/$foo/) { ## We have a match! my $tellme = tell(MYFILE)-length $_; ## See below my @baz = <MYFILE>; ## Slurp everything from that point forward unshift(@baz,$_); ## Throw our string back in ## Above, we stored the location in the file where the ## first line was that matched. Now we rewind to that point. seek(MYFILE,0,$tellme); ## The file from where we are (via seek) to the end of ## the file is now in memory, inside @baz for (@baz) { s/$foo/$bar/; print MYFILE $_; } ## Now we must cleanup our file, especially if the ## file has shrunk from our changes: truncate (MYFILE,tell(MYFILE)); last; ## Bail from the original MYFILE loop } }
In reply to Re: The easiest way to substitute a part of the content of a file.
by turnstep
in thread The easiest way to substitute a part of the content of a file.
by MF
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |