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

Say I have a file of size 2600 bytes containing gps binary. An entire GPS line is 56 bytes long. I want to read in lines that are only 56 bytes long until I encounter the last line, then I want to return that line. So far I got:
use strict; use warnings; $/ = "\n"; my $file = 'NewLogFile0.gpl'; open(FILE,$file); while( read(FILE,my $out, 56, 0){ unpack("L2d5L2",$out); print $out; } close FILE; exit
but this is just a simple converter. The thing I cant seem to figure is how to read the last line of 56 bytes. I'm going to guess that this would be easy but I could use some help. Thanks as usual.

Replies are listed 'Best First'.
Re: Reading a GPL file: Looping a Byte read
by pc88mxer (Vicar) on May 11, 2008 at 17:48 UTC
    The thing I cant seem to figure is how to read the last line of 56 bytes.
    How about getting the size, performing a little arithmetic and then seek-ing to the position of the last record?
    my $recsize = 56; open(FILE, $file) or die "open: $!"; my $size = -s FILE; my $pos = int($size / $recsize)*$recsize; seek(FILE, $pos, 0) or die "seek: $!"; read(FILE, my $out, $recsize) == $recsize or die "read: $!"; ...
Re: Reading a GPL file: Looping a Byte read
by ikegami (Patriarch) on May 11, 2008 at 18:19 UTC

    Update: Ignore this post. After rereading your node, this doesn't answer your question at all.

    local $/ = \56; while (<$file>) { # $_ contains 56 bytes. ... }

    $/

Re: Reading a GPL file: Looping a Byte read
by starbolin (Hermit) on May 11, 2008 at 21:53 UTC

    Could you clarify please? Your code implies that the data is line feed terminated. $/ = "\n"; Is this correct? Is the remainder of the file terminated with a line feed? If your records are line-feed terminated the a fixed length read needs to account for the terminator. One byte for unix, two for Windows. Are you saying that the last line is a partial line? 2600 mod ( 56 + 1) equals 4 ? Either way your last call to read() did retrieve the data and it should be in $out it's just that read returned eof. Just call unpack again after the loop terminates. You need to declare $out outside of the loop so that it is readable outside of the loop. Also be aware that if you call pack on an undersized string some values will not be returned.


    s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}