http://www.perlmonks.org?node_id=857094

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

I have a binary file which contains the data about the drive past errors and failure reasons for the same stored in the binary format. I also have the structure available which tells me what the first 8 bytes are, then the next 4 bytes and so on. I require to get the binary data parse the binary file and display drive related all errors / reasons in meaningful format to the user. I do not understand what to use - arrays, hashes in perl! I tried doing it through unpack function available in perl but i am stuck on how to get the first 8 bytes then the next 8 bytes and so on.. I will appreciate if someone can help me in this.

Replies are listed 'Best First'.
Re: Reading Binary files in Perl
by moritz (Cardinal) on Aug 25, 2010 at 08:10 UTC

    You will probably need open, binmode, read and unpack.

    If you don't get along well with pack and unpack, I can highly recommend perlpacktut, which is a gentle introduction to using those two functions.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Reading Binary files in Perl
by BrowserUk (Patriarch) on Aug 25, 2010 at 07:42 UTC

    For us to be able to help you, you'll have to tell us more.

    I also have the structure available which tells me what the first 8 bytes are, then the next 4 bytes and so on.

    A good start would be to show us what that "structure" looks like. What form is it in? How do you get it into your perl program?

    I tried doing it through unpack function available in perl but i am stuck on how to get the first 8 bytes then the next 8 bytes and so on..

    If you show us what you tried (post your non-working code here (don't forget the <code></code> tags), then it serves as a starting point from which we can guide you.

      Below is the structure or format of data in binary file: <structure> Offset Field Name size 0x0 magic_numbe 8 0x8 retry_count 1 0x9 number_record 1 0x10 dc_timestamp 8 <\structure> and the code is:
      open(FH, "<DCdata.bin") or die "Can't open DCdata.bin file for reading +!"; binmode(FH); while (<FH>) { $index = 0; foreach $field_name (keys (%disk_structure)) { $value = read (FH, $buffer, ($field_name * 8), 0); print tell (FH); print "\n"; } foreach $f_name (keys (%disk_structure_record)) { $value_record = read (FH, $buffer, ($f_name * 8), 0); #print tell (FH)\n; } } close(FILE);

        If your file consists of 18 character records, then the easiest way to read it is to set the input record separator ($/) to a reference to the number of bytes per record: $/ = \18;. This causes readline() (<FH>) to read the file as a series of fixed length records. You can then unpack the fields within each record very easily:

        #! perl -slw use strict; =comment Offset Field Name size 0x0 magic_numbe 8 0x8 retry_count 1 0x9 number_record 1 0x10 dc_timestamp 8 =cut open( FH, '<', DCdata.bin" ) or die "Can't open DCdata.bin file for reading!"; binmode(FH); $/ = \18; ## set record size while( <FH> ) { my( $magic, $retry, $recnum, $timestamp ) = unpack 'A8 C C A8', $_ +; ## Do something with the information?? } close FH;

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        A hash is not ordered, so it makes no sense to read the (ordered) elements from a file in a foreach loop over the hash keys.