Question : File Update - Expert pitonyak please note.

Hi Experts,
I have a flat file with records in
1000^email^platform^detail^status
format. pitonyak and others helped me set up the script to generate the tracking number. now my requirement is:
I have managed to get the data back into a form for update, now, when I click on update, I need a script which will scan my database, look for the track number, and update the changes, and if the status has changed, send a email.
-Help , urgent requirement.
PS: I am a newbee to perl.

Answer : File Update - Expert pitonyak please note.

OK, here is some code to perform the update. It aint quick and it aint robust. Shoot me a copy of what you finally use.

[email protected]

#
# This is not a production safe routine.
# Some issues it will not handle.
# This will fail if the file does not exist.
# File locking is not implemented.
# This assumes that NO line is longer than $max_line_len
# No check is made that the status is really the correct length.
# I assume that you want a status longer than 10.
#
use IO::file;
use StrFmt;
use Fcntl ':flock'; # import LOCK_* constants

my $max_line_len = 100;
my $status_len   = 10;

sub add_record
{
    #
    # You should probably add some error checking here
    # verify that that all of these have values
    # and see what happens when one of them is empty or something.
    #
    my ($file_name, $email, $platform, $detail, $status) = @_;
    my $fh = new IO::File;

    if ($fh->open("+<$file_name")) {
        #
        # This allows things to run in a mult-user system.
        # but not implemented on my test system
        #
        #flock($fh, LOCK_EX); # LOCK_EX is probably 2
        my $file_size = ($fh->stat())[7];
        my $new_pos = $file_size - $max_line_len;
        print "File Size = $file_size\n";
        my $next_num = 1;

        if ($file_size > 0) {
            $fh->seek($new_pos, 0) if $new_pos > 0;
            while (<$fh>) {
                my ($tmp) = /^\s*(\d+)/;
                $next_num = $tmp if defined($tmp);
            }
        }
        ++$next_num;
        $fh->seek(0, 2);
        $status = StrFmt::right_fmt($status_len, $status); # padd on the left
        my $out_line = join('^', ($next_num, $email, $platform, $detail, $status));
        print $fh "\n$out_line";
        print "$out_line\n";
        # but not implemented on my test system
        #flock($fh, LOCK_UN); # LOCK_UN is probably 8
        $fh->close();
    } else {
        print "Unable to open file $file_name because $!\n";
    }
    undef $fh;
}

sub update_record
{
    #
    # You should probably add some error checking here
    # verify that that all of these have values
    # and see what happens when one of them is empty or something.
    #
    my ($file_name, $num, $new_status) = @_;
    my $fh = new IO::File;

    if ($fh->open("+<$file_name")) {
        #
        # This allows things to run in a mult-user system.
        #
        # but not implemented on my test system
        #flock($fh, LOCK_EX); # LOCK_EX is probably 2
        #
        # This is really ineffecient. I do a linear search
        # A better solution may be to perform a binary search
        # if the file becomes larger.
        #
        my $cur_pos = $fh->tell();
        my $line = $fh->getline();
        my $done = 0;
        my $this_num = $num - 1;
        while (defined($line) && !$fh->error() && !$done) {
            chomp($line);
            $this_num = (split /\^/ , $line)[0];
            if ($this_num == $num) {
                print $line."\n";
                $done = 1;
            } else {
                $cur_pos = $fh->tell();
                $line = $fh->getline();
            }
        }
        if ($this_num != $num) {
            print "WARNING, unable to find record $num\n";
        } else {
            my $status_loc = $cur_pos + length($line) - $status_len;
            $fh->seek($status_loc, 0);
            if ($fh->tell() != $status_loc) {
                print "??Bad error, say something\n";
            } else {
                #
                # A smarter person would verify the length of the satus first.
                # if (length((split /\^/ , $line)[4]) != $status_len) {
                #   either print to this length or generate an error
                # }
                #
                my $status = StrFmt::right_fmt($status_len, $new_status); # padd on the left
                print $fh $status;
            }
        }
        # but not implemented on my test system
        #flock($fh, LOCK_UN); # LOCK_UN is probably 8
        $fh->close();
    } else {
        print "Unable to open file $file_name because $!\n";
    }
    undef $fh;
}

add_record('tst', 'email', 'OS/2', 'this is a test', 'status');
update_record('tst', 35, 'new status');


Random Solutions  
 
programming4us programming4us