Writing to a file more efficently.

Hi,
    I'm writing to a file but find the method I'm using is in-efficent.  What I do is read in a file, store it in a array, modify the corressponding array element to the line number and then print everything back to the file.  Is there a simplier way to just write a single line to a file?  So if I wanted to just write line 2 over in a 5 line file, I wouldn't have to touch any other lines.

Thanks in Advance.
cideAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
tpryorConnect With a Mentor Commented:
i would suggest using the "tie" keyword in perl 5.  You can tie a hash or an array to a text file.  When you write to the array/hash it writes to that line in the text file.

for example if you use TieFile.pm you could say...

tie @lines, TieFile', 'foo.txt';
print $lines[20];

When asked to fetch the nth line the TieFile module reads the file until it reaches that line and returns it.  Since it is wasteful to keep traversing the entire file every time a line is requested, TieFile keeps track of the file offsets of the beginning of each line so that when you ask it for a line that it has already visited, it knows the precise offset to seek before reading.

so the file is not stored in an array in memory and you can deal with the file on a specific line by line basis.

is this  what your looking for?

let me know I'll paste the TileFile.pm here.

GL
t
0
 
ozoCommented:
perl -i.old -pe '$_ = "new line 2\n" if $.==2' file
0
 
cideAuthor Commented:
So do I actually use this line in the perl script?
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
rkulperCommented:
Since the -i option rewrites the entire file anyway, I do not think it is any more efficient than what your currently doing. See perldoc perlrun -i option.

You could use the tell and seek functions, but this only works efficiently if all the line lengths are equal. If the line lengths are not equal, the only optimization I can think of is to use tell and seek to avoid changing the first unused part of the file.

Here is an example program that sorts the file "passwd" (assuming passwd contains lines of equal length).

#!/usr/local/bin/perl
$index=1; $position[0]=0;
unless (open FILE, "+<passwd") {
            print STDERR "Unable to open file: $!\n";
            exit;
}
while (<FILE>) {
      $array[$index]=$_;
      $position[$index]=tell FILE;
      $index++;
}
@sorted=sort @array;
$index=0;
while ($index <= $#array) {
      if($array[$index] ne $sorted[$index]) {
            seek FILE, $position[$index], 0;
            print FILE $sorted[$index];
      }
      $index++;
}
close FILE;
0
 
ozoCommented:
It is more efficient in that it does not store the entire file in n array.  see
perldoc perlfaq5

("passwd" may be a poor example of a file assumed to contain lines of equal length)
Also, starting at $index = 1 may make the ne between @lines and @sorted work differently than you intended.
I'd have just used push and shift, and not bother with $index at all.
0
 
cideAuthor Commented:
What is this -i option everyone is talking about?
0
 
ozoCommented:
see
perldoc perlrun
Within a script, you could also use

{local $^I=".old"; local @ARGV=("file.name");
while( <> ){
  $_ = "new line 2\n" if 2..2;
  print;
}
}

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.