Чтение двоичного файла с помощью 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
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"
Да, потому что ваш второй аргумент для распаковки - "a128ac" и руководство (http://jp2.php.net/manual/en/function.pack.php ) говорит, что "а" означает "строка с нулевым заполнением", но вы, возможно, хотите "А", которая является "строкой с пробелом". То, что вы видите, - мусор, потому что терминатор не найден должным образом.