使用PHP读取二进制文件

4

这是使用的'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 us 12.23 34.12 90.12 fees 12 56.12 01/01/1998 a us 52.23 54.12 10.12 fees 92 16.12 31/12/1999 a us 52.23 54.12 10.12 fees 92 16.12 31/12/1999 d us 12.23 34.12 90.12 fees 12 56.12 01/01/2000 a us 52.23 54.12 10.12 fees 92 16.12 01/01/2000 z us 12.23 34.12 90.12 fees 12 56.12 31/12/2010 a us 52.23 54.12 10.12 fees 92 16.12 31/12/2010 d us 12.23 34.12 90.12 fees 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 d¸³M·g·ew·¤dw·àew·Öúr·ÿÿÿÿ,w·ø;w·Ìª¹¿ô{·{·‹ây·Ð{·SpP·ip·¤dw·ew·€5w·ôOg· X«¹¿»qP·äSg us 12.229999542236 34.119998931885 90.120002746582 fees·5rP· #Ä äSg· rP·ô›Å #Ä 5rP·0#o·¸xw·x«¹¿·ÅÿÿýŽäSg·¸xw·ÆD¬¹¿L¬¹¿5rP·pòy· 12 56.119998931885

01/01/1998 a¸³M·g·ew·¤dw·àew·Öúr·ÿÿÿÿ,w·ø;w·Ìª¹¿ô{·{·‹ây·Ð{·SpP·ip·¤dw·ew·€5w·ôOg· X«¹¿»qP·äSg us 52.229999542236 54.119998931885 10.119999885559 fees·5rP· #Ä äSg· rP·ô›Å #Ä 5rP·0#o·¸xw·x«¹¿·ÅÿÿýŽäSg·¸xw·ÆD¬¹¿L¬¹¿5rP·pòy· 92 16.120000839233

31/12/1999 a¸³M·g·ew·¤dw·àew·Öúr·ÿÿÿÿ,w·ø;w·Ìª¹¿ô{·{·‹ây·Ð{·SpP·ip·¤dw·ew·€5w·ôOg· X«¹¿»qP·äSg us 52.229999542236 54.119998931885 10.119999885559 fees·5rP· #Ä äSg· rP·ô›Å #Ä 5rP·0#o·¸xw·x«¹¿·ÅÿÿýŽäSg·¸xw·ÆD¬¹¿L¬¹¿5rP·pòy· 92 16.120000839233

31/12/1999 d¸³M·g·ew·¤dw·àew·Öúr·ÿÿÿÿ,w·ø;w·Ìª¹¿ô{·{·‹ây·Ð{·SpP·ip·¤dw·ew·€5w·ôOg· X«¹¿»qP·äSg us 12.229999542236 34.119998931885 90.120002746582 fees·5rP· #Ä äSg· rP·ô›Å #Ä 5rP·0#o·¸xw·x«¹¿·ÅÿÿýŽäSg·¸xw·ÆD¬¹¿L¬¹¿5rP·pòy· 12 56.119998931885

01/01/2000 a¸³M·g·ew·¤dw·àew·Öúr·ÿÿÿÿ,w·ø;w·Ìª¹¿ô{·{·‹ây·Ð{·SpP·ip·¤dw·ew·€5w·ôOg· X«¹¿»qP·äSg us 52.229999542236 54.119998931885 10.119999885559 fees·5rP· #Ä äSg· rP·ô›Å #Ä 5rP·0#o·¸xw·x«¹¿·ÅÿÿýŽäSg·¸xw·ÆD


1
很可能是编译器输出文件的字符编码方式与php脚本打开文件的方式不同。尝试找出该编码类型,并在指定如何读取文件的同时,在php中打开该文件。 - Florin Stingaciu
2个回答

0
在PHP的packunpack中,格式化代码a代表NUL 填充字符串。在这种情况下,第二个和第七个字段似乎没有进行NUL填充;它们只是有一个NUL来表示字符串的结束,然后是随机数据。
要获取NUL之前的字符串部分,可以使用substrstrpos
$input = "a\000b"; // string with embedded NUL 
$output = substr($input, 0, strpos($input, "\000"));
var_dump($output); // string(1) "a"

浮点数字段具有其正确的值,您从C程序输出中看到的值是四舍五入的。在PHP中,您可以使用sprintf来执行相同的操作,例如:
$input = 16.120000839233;
$output = sprintf("%.2f", $input);
var_dump($output); // string(5) "16.12"

0

是的,因为你传给unpack的第二个参数是"a128ac",而手册(http://jp2.php.net/manual/en/function.pack.php)说"a"代表"NUL填充字符串",但你可能想要的是"A",它代表"空格填充字符串"。你看到的是垃圾数据,因为终止符没有被正确地找到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接