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

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

I have written the data(contents of structure which are records) in file using fread function in C.How can I read that file contents in Perl.I tried with binmode , but I didn't get the result.Please give me any idea.

Replies are listed 'Best First'.
Re: Read structure in Perl
by BrowserUk (Patriarch) on Mar 22, 2010 at 11:24 UTC
    I have written the data ... in file using fread function in C

    You wrote with fread()?

    You'll need to detail what you wrote and how you wrote it. Preferably, post the C code you used to write it. Or the C code you would use to read it correctly.


    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.
      I have written the records in the file using following way.
      #include <stdio.h> #include <string.h> #include <malloc.h> #define DSZ 108 struct stud { char name[100]; int roll_no; }; struct student { struct stud s; int grade; }value; int main() { FILE *fps; struct student *buffer=(struct student*)malloc(sizeof(struct s +tudent)); int n,j; fps=fopen("Myfile","wb+"); value.s.roll_no=149; value.grade=1; strcpy(value.s.name,"myname"); n=fwrite(&value,DSZ,1,fps); rewind(fps); n=fread(buffer,DSZ,1,fps); printf("Name:%s Grade:%d NO:%d\n",buffer->s.name,buffer->grade +,buffer->s.roll_no); fclose(fps); }

        Try this. '<:raw' is roughly equivalent to binmode. The unpack templates: 'A100' tells it to treat the first 100 bytes as a null terminated string; 'i'(*) means treat the next 4 bytes as a signed integer.

        #! perl -slw use strict; open IN, '<:raw', $ARGV[ 0 ] or die $!; my $binary = do{ local $/; <IN> }; ## read the whole file close IN; my( $name, $roll_no, $grade ) = unpack 'A100 i i', $binary; print "name: $name; no:$roll_no; grade:$grade"; __END__ C:\test>junk58 Myfile name: myname; no:149; grade:1
        (*If the data is read on a different hardware platform from that where it is written you may need to change the 'i' template.)

        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.
        Another alternative is to use Inline::C. This reads 'Myfile' correctly for me:
        use warnings; use Inline C => <<'EOC'; #define DSZ 108 struct stud { char name[100]; int roll_no; }; struct student { struct stud s; int grade; }value; void foo(char * fn) { FILE *fps; int n; struct student *buffer=(struct student*)malloc(sizeof(struct stud +ent)); fps=fopen(fn,"rb"); n=fread(buffer,DSZ,1,fps); printf("Name:%s Grade:%d NO:%d\n",buffer->s.name,buffer->grade,bu +ffer->s.roll_no); fclose(fps); } EOC foo("Myfile"); # outputs: # Name:myname Grade:1 NO:149
        It's trivial to return the values to perl, if need be (rather than simply print them to stdout). And if it's necessary to use perl's IO abstraction interface (see perldoc perlapio) instead of the usual C functions, then I think that could be accommodated, too.

        Cheers,
        Rob
Re: Read structure in Perl
by DrHyde (Prior) on Mar 22, 2010 at 11:23 UTC
    You appear to have forgotten to include a sample of the data, the perl code, and an explanation of how its output differs from what you want. I'm sure you *meant* to include those, because obviously, without them, no-one can help you.
Re: Read structure in Perl
by ctilmes (Vicar) on Mar 22, 2010 at 11:47 UTC
    As others note, more details are needed to really give you the answer.

    The general Perl way to unpack structures such as those typically read by fread in C may involve use of the unpack function.

      As a hard-core alternative to unpack, there is Convert::Binary::C, which can take a C structure and a C compiler (even one for a different architecture), and unpack data in that C structure from Perl.

        Thanks for the tip!

        Looks like less work in the long run. Hardcore indeed!