如何拆分二进制数据并将其转换为PHP中的数字?
How to split binary data and convert it into numbers in PHP?
我正在读取来自 /dev/input/
的键盘事件。这些是 input_event structs,分别是小端格式的 24 个字节的五个数字。
这是我目前的解决方案:
$hex = bin2hex(fread($dev, 24));
$time = floatval(unpack("Q", (pack('H*', substr($hex, 0, 16))))[1].".".unpack("Q", (pack('H*', substr($hex, 16, 16))))[1]);
$type = intval(unpack("S", (pack('H*', substr($hex, 32, 4))))[1]);
$code = intval(unpack("S", (pack('H*', substr($hex, 36, 4))))[1]);
$value = intval(unpack("l", (pack('H*', substr($hex, 40, 8))))[1]);
必须 是在 PHP 中执行此操作的更有效方法。任何人?布勒?
更新:
Blob 示例为:
$raw = hex2bin("f478cd5d0000000026680d000000000001002e0001000000");
这导致:
$time = 1573746932.8786;
$type = 1;
$code = 46;
$value = 1;
实际结构如下所示:
struct input_event {
timeval time;
__u16 type;
__u16 code;
__s32 value;
};
时间间隔是:
struct timeval {
__u64 sec;
__u64 usec;
}
据我所知,没有真正的浮点值:
(gdb) ptype struct input_event
type = struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
}
(gdb) ptype struct timeval
type = struct timeval {
__time_t tv_sec;
__suseconds_t tv_usec;
}
(gdb) ptype __time_t
type = long
(gdb) ptype __suseconds_t
type = long
(gdb) ptype __u16
type = unsigned short
(gdb) ptype __u16
type = unsigned short
(gdb) ptype __s32
type = int
既然是这种情况,您只需做一些二进制工作即可:
<?
// Converts your data to byte array
$d = unpack('C*', fread($dev, 24));
// Calculate whatever you desire ...
$tv_sec = ($d[1]<<56) + ($d[2]<<48) + ($d[3]<<40) + ($d[4]<<32) + ($d[5]<<24) + ($d[6]<<16) + ($d[7]<<8) + ($d[8]<<0);
?>
这只是一个基本示例 - 我懒得检查字节顺序。
您可以将其解包为单个值。
<?php
$raw = fread($dev, 24);
$data = unpack("Ptime1/Ptime2/vtype/vcode/Vvalue", $raw);
print_r($data);
输出:
Array
(
[time1] => 1573746932
[time2] => 878630
[type] => 1
[code] => 46
[value] => 1
)
我正在读取来自 /dev/input/
的键盘事件。这些是 input_event structs,分别是小端格式的 24 个字节的五个数字。
这是我目前的解决方案:
$hex = bin2hex(fread($dev, 24));
$time = floatval(unpack("Q", (pack('H*', substr($hex, 0, 16))))[1].".".unpack("Q", (pack('H*', substr($hex, 16, 16))))[1]);
$type = intval(unpack("S", (pack('H*', substr($hex, 32, 4))))[1]);
$code = intval(unpack("S", (pack('H*', substr($hex, 36, 4))))[1]);
$value = intval(unpack("l", (pack('H*', substr($hex, 40, 8))))[1]);
必须 是在 PHP 中执行此操作的更有效方法。任何人?布勒?
更新:
Blob 示例为:
$raw = hex2bin("f478cd5d0000000026680d000000000001002e0001000000");
这导致:
$time = 1573746932.8786;
$type = 1;
$code = 46;
$value = 1;
实际结构如下所示:
struct input_event {
timeval time;
__u16 type;
__u16 code;
__s32 value;
};
时间间隔是:
struct timeval {
__u64 sec;
__u64 usec;
}
据我所知,没有真正的浮点值:
(gdb) ptype struct input_event
type = struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
}
(gdb) ptype struct timeval
type = struct timeval {
__time_t tv_sec;
__suseconds_t tv_usec;
}
(gdb) ptype __time_t
type = long
(gdb) ptype __suseconds_t
type = long
(gdb) ptype __u16
type = unsigned short
(gdb) ptype __u16
type = unsigned short
(gdb) ptype __s32
type = int
既然是这种情况,您只需做一些二进制工作即可:
<?
// Converts your data to byte array
$d = unpack('C*', fread($dev, 24));
// Calculate whatever you desire ...
$tv_sec = ($d[1]<<56) + ($d[2]<<48) + ($d[3]<<40) + ($d[4]<<32) + ($d[5]<<24) + ($d[6]<<16) + ($d[7]<<8) + ($d[8]<<0);
?>
这只是一个基本示例 - 我懒得检查字节顺序。
您可以将其解包为单个值。
<?php
$raw = fread($dev, 24);
$data = unpack("Ptime1/Ptime2/vtype/vcode/Vvalue", $raw);
print_r($data);
输出:
Array
(
[time1] => 1573746932
[time2] => 878630
[type] => 1
[code] => 46
[value] => 1
)