Чтение двоичного файла с помощью PHP


Это используемая структура "C++".

struct gross
    {
        char date[11];
        char ac[128];
        char type[5];
        float mvalue;
        float netraw;
        float netfer;
        char stat[128];
        float firr;
        float acb;
    };

Это содержимое двоичного файла, созданного при компиляции с помощью компилятора GCC.

12.12.1995 d США 12.23 34.12 90.12 сборы 12 56.12 01/01/1998 a 52.23 54.12 США 10.12 сборы 92 16.12 31.12.1999 a 52.23 54.12 10.12 сборы в США 92 16.12 31.12.1999 d США 12.23 34.12 90.12 сборы 12 56.12 01/01/2000 a США 52.23 54.12 10.12 сборы 92 16.12 01/01/2000 z США 12.23 34.12 90.12 сборы 12 56.12 31.12.2010 a 52.23 54.12 10.12 сборы в США 92 16.12 31/12/2010 d США 12.23 34.12 90.12 сборы 12 56.12

PHP-кодирование для чтения содержимого вышеупомянутого двоичного файла.

echo "<table>";
while (!feof($f)) {

  if ($s = fread($f, 292)) {

        $nn = unpack('a11date/a128ac/a5type/fmvalue/fnetraw/fnetfer/a128stat/ffirr/facb', $s);

        echo "<td>" . $nn[date] ."</td>";
        echo "<td>" . $nn[ac] . "</td>";
        echo "<td>" . $nn[type] . "</td>";
        echo "<td>" . $nn[mvalue] . "</td>";
        echo "<td>" . $nn[netraw] . "</td>";
        echo "<td>" . $nn[netfer] . "</td>";
        echo "<td>" . $nn[stat] . "</td>";
        echo "<td>" . $nn[firr] . "</td>";
        echo "<td>" . $nn[acb] . "</td>";
        echo "</tr>";
 }
}
        echo "</table>";
fclose($f);
?>

Вот что я получил из приведенного выше кода. То, что я получаю, - это множество мусорных значений во втором и седьмом полях. И точность превышает для полей с плавающей точкой. Как это исправить?

12.12.1995 d3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·5 Вт·Ог· X"1¿"QP·äsg us 12.229999542236 34.119998931885 90.120002746582 сборы·5RP·#Äsg·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5rp·pòy·12 56.119998931885

01/01/1998 a3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·€5 Вт·"Ог· X"1¿"QP·ÄSG сша 52.229999542236 54.119998931885 10.119999885559 сборы·5RP·#Äsg·RP·"Å#Ä 5RP·0#o·xw·x"1¿·åïïýžäsg·xw·ÆD1¿L1¿5RP·pòy·92 16.120000839233

31/12/1999 a3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·€5 Вт·"Ог· X"1¿"QP·ÄSG сша 52.229999542236 54.119998931885 10.119999885559 сборы·5RP·#Äsg·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5rp·pòy·92 16.120000839233

31/12/1999 d3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·5 Вт·Ог· X"1¿"QP·äsg США 12.229999542236 34.119998931885 90.120002746582 сборы·5RP·#Ä ÄSG·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5RP·pòy·12 56.119998931885

01/01/2000 a3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·€5 Вт·"Ог· X"1¿"QP·ÄSG сша 52.229999542236 54.119998931885 10.119999885559 сборы·5RP·#Äsg·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5rp·pòy·92 16.120000839233

01/01/2000 z3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·€5 Вт·"Ог· X"1¿"QP·äsg сша 12.229999542236 34.119998931885 90.120002746582 сборы·5RP·#Ä ÄSG·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5rp·pòy·12 56.119998931885

31/12/2010 a3m·g·ew·¤dw·aew·Ор·ÿÿÿ, вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·€5 Вт·"Ог· X"1¿"QP·ÄSG сша 52.229999542236 54.119998931885 10.119999885559 сборы·5RP·#Äsg·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5rp·pòy·92 16.120000839233

31/12/2010 D3m·g·ew·¤dw·aew·Öúr·ÿÿÿ,вт·ø; вт·Ì1¿"{·{·"ы·Ð{·SPP·ip·¤dw·ew·€5 Вт·"Ог· X"1¿"QP·äsg us 12.229999542236 34.119998931885 90.120002746582 сборы·5RP·#Äsg·RP·"Å#Ä 5rp·0#o·xw·x"1¿·Åÿýžäsg·xw·ÆD1¿L1¿5rp·pòy·12 56.119998931885

Author: Emmi, 2012-06-08

2 answers

В PHP pack и unpack код форматирования a обозначает строку NUL с дополнением . В этом случае похоже, что второе и седьмое поля не заполнены нулем; у них просто есть NUL, чтобы указать, где заканчивается строка, за которой следуют случайные данные.

Чтобы получить часть строки до NUL, вы можете использовать substr и strpos:

$input = "a\000b"; // string with embedded NUL 
$output = substr($input, 0, strpos($input, "\000"));
var_dump($output); // string(1) "a"

Поля с плавающей точкой имеют правильные значения, значения, которые вы видите в выходных данных программы на языке Си, округлены. Чтобы сделать то же самое в PHP вы могли бы использовать sprintf, например:

$input = 16.120000839233;
$output = sprintf("%.2f", $input);
var_dump($output); // string(5) "16.12"
 0
Author: Joni, 2012-06-08 08:17:35

Да, потому что ваш второй аргумент для распаковки - "a128ac" и руководство (http://jp2.php.net/manual/en/function.pack.php ) говорит, что "а" означает "строка с нулевым заполнением", но вы, возможно, хотите "А", которая является "строкой с пробелом". То, что вы видите, - мусор, потому что терминатор не найден должным образом.

 0
Author: Tõnu Samuel, 2012-06-08 08:10:32