Search code examples
phparraysfilebinaryfilesunpack

Why can't compress many unpack statements into one as the form of unpack("Lfffffff",$bytes)?


<?php
//it is unnecessary to get the data file.
    $handle = fopen('data', 'rb');
    fread($handle,"64");
//it is no use to parse the first 64 bytes here.
    $bytes= fread($handle,"4");
    print_r(unpack("L",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
    $bytes= fread($handle,"4");
    print_r(unpack("f",$bytes));
    echo  "<br/>";
?>

I got the right output with the code.

Array ( [1] => 20150416 )
Array ( [1] => 1.0499999523163 )
Array ( [1] => 1.25 )
Array ( [1] => 1.0299999713898 )
Array ( [1] => 1.1900000572205 )
Array ( [1] => 509427008 )
Array ( [1] => 566125248 )
Array ( [1] => 509427008 ) 

Now I want to compress many unpack statements into one as the form of unpack("Lfffffff",$bytes) with the following code.

<?php
    $handle = fopen('data', 'rb');
    fread($handle,"64");
    //it is no use to parse the first 64 bytes here.
    $bytes= fread($handle,"32");
    print_r(unpack("Lfffffff",$bytes));
?>

Why I get the only one output,no other parsed data in my result? How to fix it?

Array ( [fffffff] => 20150416 ) 

The data file was opened with notepad++ and check by the plugin--TextFX . Only 96 bytes parsed here,the first 64 bytes omitted by fread.

enter image description here


Solution

  • From the unpack doc:

    The unpacked data is stored in an associative array. To accomplish this you have to name the different format codes and separate them by a slash /. If a repeater argument is present, then each of the array keys will have a sequence number behind the given name.

    Try this example:

    <?php
    
    $array = array (20150416, 1.0499999523163, 1.25, 1.0299999713898, 1.1900000572205, 509427008, 566125248, 509427008);
    
    $output = pack('L', $array[0]);
    
    for($i = 1; $i < 8; $i++) {
        $output .= pack('f', $array[$i]);
    }   
    
    print_r(unpack("LL/f7", $output));
    
    ?>
    

    In unpack("LL/f7", $output) the first L refers to unsigned long the second L to the index in the array (see the first element in the output) the / (read the first part of the answer) and f refers to float and the 7 to seven float values.

    Output:

    Array
    (
        [L] => 20150416
        [1] => 1.0499999523163
        [2] => 1.25
        [3] => 1.0299999713898
        [4] => 1.1900000572205
        [5] => 509427008
        [6] => 566125248
        [7] => 509427008
    )
    

    In your case should be:

    <?php
        $handle = fopen('data', 'rb');
        $bytes= fread($handle,"32");
        print_r(unpack("LL/f7",$bytes));
    ?>