[EMAIL PROTECTED] wrote:
I'm a C/C++ programmer, with a perl script I'm trying to optimize.  I
don't know enough about perl syntax and string/buffer handling
functions to feel comfortable doing this on my own.

Perl's open()/read() functions are equivalent to C's fopen()/fread() and so the IO is buffered. Perl's sysopen()/sysread() functions are equivalent to C's open()/read() and so the IO is not buffered.

perldoc perlopentut
perldoc -f open
perldoc -f read
perldoc -f sysopen
perldoc -f sysread


I imagine adding
some 'regular expressions' would be ideal, in place of my while()
loop.  If anyone wouldn't mind giving me a hand with this, I'd really
appreciate it, and I also figure at the very least... by posting this
code it might help someone else looking for a solution like this (even
if my code is really slow).

I have a file on my web-site that users can download using this
script, and only by using this script.  The script injects some
information in to the file while sending it, since I need different
info for each user and didn't really want to mess with temp files or
anything like that.  This script works great, but it takes several
minutes to download a 5 MB file, which I can download directly (bypass
the script) in about 30 seconds.

$hostname is set to whatever I need to inject by some code above this
part, and $search is the data I need to replace with $hostname (they
are always the same length, so it never changes the size of the
downloaded file).  The loop at the end is what I imagine needs to be
faster.  I'm not sure if it would be safe or possible to read in the
entire file in one block, then just work on that buffer... would
probably use up too much memory on the server if I did that.

# Open the input file for reading
open IN, "< $infile"
    or die "Can't open $infile: $!";

You should probably use the three argument open (and you can skip the separate binmode().)

open IN, '<:raw', $infile or die "Can't open $infile: $!";


# Our EXE is a binary file
binmode IN;

# Get the file info
my @info = stat(IN);
my $length = $info[7];

You don't need the @info array, just assign the eighth element directly:

my $length = ( stat IN )[ 7 ];

Or just use the -s file test operator:

my $length = -s IN;


my $blksize = 1;

You are setting your read $buffer to one byte!? Even in C with buffered IO reading one byte at a time is usually a bad idea.


# Send the HTTP header
print "Content-type: application/octet-stream\n";
print "Content-Length: $length\n";
print "Content-Disposition: attachment; filename=\"webinst.exe\"\n";
print "\n";

# Make sure that the output is written in
# binary mode and buffered
binmode STDOUT;
select STDOUT; $|=1;

# This is used to track our progress while searching for $search
string.
my $sx = 0;

# Read each chunk of the input file
# and pass it to the browser
#  This will replace each occurance of '$search' with '$hostname'
#   as it sends the file.
my $buffer;
while (!eof(IN))
   {
   read(IN, $buffer, $blksize);

In perl you almost *never* need to use the eof() function. That is usually written as:

while ( read IN, $buffer, $blksize )
    {

But even that doesn't report any errors that read() may encounter.

while ( my $read = read IN, $buffer, $blksize )
    {
    defined $read or die "Cannot read from '$infile' $!";


   my $ch1 = substr($buffer,0,1);

Since $buffer only contains one byte there is no point in using substr().


   my $ch2 = substr($search,$sx,1);

   if(uc($ch1) eq uc($ch2))
      {
      $sx++;
      if($sx eq length($search))

$sx and length($search) are numbers so you should use the correct comparison operator:

       if ( $sx == length( $search ) )


         {
         $sx = 0;
         print $hostname;
         }
      }
   else
      {
      if($sx > 0)
         {
         print substr($search,0,$sx);
         $sx = 0;
         }
      print $buffer;
      }
   }

close IN;
exit 0;

If possible you should try reading the entire file into a scalar and use the substitution operator or at least use a buffer larger than one byte.



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order.                            -- Larry Wall

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to