用PHP解压缩二进制文件

时间:2017-07-28 17:06:41

标签: php binary unpack

我试图在PHP中解析二进制文件,它是NoSQL DB中Document的附件。但是,在我的测试中,如果文件大小为1MB,则解压缩持续大约12-15秒。该文件包含有关传感器速度的信息。

转换为十六进制的二进制文件的结构如下:

BB22 1100 0015 XXXX ...
BB22 1300 0400 20FB 5900 25FB 5910 ... 20FB 5910
BB22 1100 0015 ...
BB22 1300 0400 20FB 5700 25FB 5810 ... 20FB 5912
BB22 1300 0400 20FB 5700 25FB 5810 ... 20FB 5912
...

标记BB22 1100包含传感器规范,而0015表示该信息的大小。

标记BB22 1300包含其他数据加上传感器的实际速度。接下来的两个字节0400表示该块的长度,即1024字节。

我只对速度感兴趣,例如价值5900 5910 5910 5700 5810 ...

我的方法如下:

$file = fopen($url, 'r', false, authenticationContext($url));
$result = stream_get_contents($file, -1);
fclose($file);

$hex_result = bin2hex($result);

$markerData = 'bb2213';
$sensorDataUnpack= "sspeed"; // signed int16 

while(($pos = strpos($hex_result, $markerData, $pos)) !== FALSE){
    $pos=$pos+4;
    for ($j=4; $j<1028; $j=$j+4) { 
       $d =  unpack($sensorDataUnpack, substr($result, $pos/2+$j+2));       
       $sensorData[] = $d; 
    }
}

我将结果从二进制转换为十六进制,因为它不适合我正确获取位置。无论如何,我相信这段代码可以得到很大的改进,任何想法?

1 个答案:

答案 0 :(得分:0)

这应该很快,但如果没有测试数据我就无法测试它。

关键点是:

  • 将URL打开为二进制文件,并使用fread()来帮助定位和将数据切片到部分。
  • 使用解压缩来解析标题和条目的正文。
  • 使用星号*转发器快速解析签名短裤的大型实体。
  • 使用array_values()将关联数组转换为带数字键的简单数组(如:0,1,2,...)。

更新:我通过使用&#34; H4&#34;解决了标记比较周围的字节顺序和位数问题。打包格式以大端顺序获取hexa字符串。

    $sensorData = array();
    $file = fopen($url, 'rb', false, authenticationContext($url));

    while (($header = fread($file, 6)) !== false) {
        $fields = unpack("H4marker/ssize", $header);

        $body = fread($file, $fields["size"] * 2);

        if ($body === false) {
            throw new Exception("import: data stream unexpectedly ended.");
        }

        if ($fields["marker"] == "BB221300") {
            $data = array_values(unpack("s*", $body));

            // Store only every second value.
            for ($i = 1; $i < count($data); $i+=2) {
                $sensorData[] = $data[$i];
            }
        }
    }

    fclose($file);