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

Greetings

I'm trying to arrange a process of saving double or single precison numbers to a binary file for later access via C or VB code. Another factor is that the file has to be saved either in little endian or big endian mode.

I've found this code:

open(my $out, '>:raw', 'sample.bin') or die "Unable to open: $!"; print $out pack('s<',255) ; close($out);

which is supose to save the value 255 as a short variable. Can someone please help me to create a process to save a sequence of 2 or 3 numbers, either in single or double precision, and either in big or little endian? I supose that the sequencial part is made by the append operator (my $out, '>>:raw', 'sample.bin'), and the double or single precision with a letter diferent of 's' (maybe 'd'?). As for the little/big endian, I have no idea...

Kind regards,

Kepler

Replies are listed 'Best First'.
Re: Perl binary file
by BillKSmith (Monsignor) on Dec 30, 2017 at 20:59 UTC
    The hardest part of this task is determining exactly what you need. I suggest that you write a program in "C" that writes a sample file. Verify that this file can be read correctly. When you have a working sample, examine it with a hex editor to answer several questions. Are there any extra characters in the file (e.g. newlines)? Is your understanding of "single" and "double" precision correct? Is the data "big endian"? Are the "nibbles" swapped within each byte? Given the answers to these questions, it should not be hard to write the correct format for 'pack'. Now try to write the same data with perl. Examine the output file with your hex editor. It should be identical to the one you made with "C". If not, how is it different? If you still need help, post the hex dumps of the two files. It probably would help if you also post the "C" and perl programs you used to create them.
    Bill
Re: Perl binary file
by kepler (Scribe) on Dec 29, 2017 at 08:37 UTC

    Hi

    After some digging, would this work?

    print $out pack('f<',2.5) ; #single, little endian print $out pack('d<',2.5) ; #double, little endian print $out pack('f>',2.5) ; #single, big endian print $out pack('d>',2.5) ; #single, big endian

    Is there a diference between 'd' or 'D' (or 'f' and 'F')which can create incompatible issues? And as far the append, will it be sequencial?

    Kind regards

    Kepler

      perldoc pack says F is "Perl internal format", perlpacktut under "Floating point Numbers" is a bit more helpful, but not very…

      'd' or 'D'
      These are C double and long double, respectively. They are probably different. On Intel machines, long double is usually an 80-bit non-IEEE754 type while double is standard IEEE-754 double precision type.

      'f' and 'F'
      These are C float and "whatever Perl uses internally". Again, on Intel machines float usually represents IEEE-754 single precision type, while NV would be even less portable than long double (because a user could rebuild their Perl with different definition for NV) but priceless for exact data caching in between the runs of your own application.

      To answer your original question, use f for IEEE-754 single precision, d for IEEE-754 double precision types compatible with C and VB (if float and double do not correspond to IEEE types on a given system, chances are it doesn't support IEEE types at all and such processors are rare enough that you probably shouldn't worry about them) and > for big-endian (most significant byte first; "network byte order"), < for little-endian (least significant byte first; "Intel byte order"). Also, you were right, to sequentially append to binary files, just use open (my $fh, ">>:raw", $filename);.

Re: Perl binary file
by Anonymous Monk on Dec 29, 2017 at 09:18 UTC