Scott Haneda wrote:
>
> Hi Rob, thanks for your reply.  This is my first adventure into perl,  
> and I am a bit stumped.  I have experience in a few web scripting  
> languages, but this is a little new to me.
> 
> Your script does work, and returns a number, but not the correct one,  
> and I think it has to do with my in file being in a strange format.   
> It is a email Inbox, the message count is told to me by the developer  
> to be 4 bytes in, 4 bytes long, and a big endian value.  I just want  
> the mailbox count of messages out of it, which the C code below did in  
> fact do.  I just have issues moving that C binary to other machines,  
> and perl will be more universal.
> 
> I zipped a file and put it up, it should have 8 messages in it.  The  
> developer of the email server is not as forthcoming with help in this  
> regard, so I am at a loss for a lot of data on the format of the file.
> 
> There is a sample file here:
> http://www.newgeo.com/web/misc/62315-testbox.zip
> 
> If you would not mind taking a look at it, I will post a follow up to  
> the list explaining how it all works, as soon as I understand it.
> 
> I put a few comments inline below about your code.
> 
>>> Hello, I have this small C app that someone wrote for me ages ago,  
>>> and
>>> am tired of it breaking every time I move it around to various
>>> systems, I will include it below.
>>>
>>> I am hoping I can do this in perl, as a one liner, were it will  
>>> read a
>>> the first 4 bytes of a file, grab 4 bytes out of the file, which is a
>>> big endian value, and return that as an int to me.
>>>
>>> Here is the basic C app I have been using:
>>>
>>> #include <stdio.h>
>>> #include <libkern/OSByteOrder.h>
>>>
>>> int main (int argc, char *argv[]) {
>>>     FILE* fd;
>>>     char buffer[8];
>>>     unsigned long int dv;
>>>
>>>     //open the file
>>>     fd = fopen(argv[1], "r");
>>>     printf("Filename: %-50s", argv[1]);
>>>
>>>     fread(buffer, 1, sizeof(buffer), fd);
>>>     dv = OSReadBigInt32(buffer, 4);
>>>
>>>     // print the decimal value
>>>     printf(" Value: %ld\n", dv);
>>>
>>>     return 0;
>>> }
>> use strict;
>> use warnings;
>>
>> my $file = shift;
>>
>> open my $fh, '<', $file or die $!;
>> print "Filename: $file";
> 
> Is there no need to close the file handle?  If not, what harm is there  
> in leaving it open?
> 
>> my $buffer;
>> my $count = read $fh, $buffer, 4 or die $!;
>> die "Insufficient data in file" unless $count >= 4;
>>
>> my $dv = unpack 'N', $buffer;
>> print " Value: $dv\n";
> 
> I just read the docs on unpack, and I do not follow what the purpose  
> is here?

OK, first of all the correction. I didn't know the function of OSReadBigInt32
and assumed the second parameter was a byte count. It seems that it's actually a
byte offfset, so we need to read in eight bytes to start with and convert the
last four to a big-endian longword. Version 0.2 is below and I hope it gives you
the right value this time.

Now for the questions.

- Using a lexical scalar file handle conveniently closes the file when the
  scalar goes out of scope. In this case it will be closed at the end of the
  program, but it's a good habit to get into to restrict file operations to a
  small scope and rely on automatic closure. Something like this, for example

  my $first_line;
  {
    open my $fh, '<', $infile or die $!;
    $first_line = <$fh>;
  }

  which will open the file, read the first line and close it, leaving only the
  required data still existing.


- The bulk of the documentation on 'unpack' is in

  perldoc -f pack

  and the new unpack format moves to a character offset of 4 (@4) and extracts a
  32-bit big-endian integer (N).

Finally, please post to the group and not directly to me, so that others can
both help and be helped by the dialogue. Thanks.

HTH,

Rob




use strict;
use warnings;

my $file = shift;

open my $fh, '<', $file or die $!;
print "Filename: $file";

my $buffer;
my $count = read $fh, $buffer, 8 or die $!;
die "Insufficient data in file" unless $count >= 8;

my $dv = unpack '@4 N', $buffer;
print " Value: $dv\n";

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


Reply via email to