将php数据转换为二进制数据
string pack ( string $format [, mixed $args [, mixed $...]] )
将二进制数据转换为php数据
array unpack ( string $format, string $data )
$format:
a – NUL-padded string
a – NUL- 字符串填满[padded string]
A – SPACE-padded string
A – SPACE- 字符串填满[padded string]
h – Hex string, low nibble first
h – 十六进制字符串,低“四位元”[low nibble first]
H – Hex string, high nibble first
H – 十六进制字符串,高“四位元”[high nibble first]
c – signed char
c – 带有符号的字符
C – unsigned char
C – 不带有符号的字符
s – signed short (always 16 bit, machine byte order)
s – 带有符号的短模式[short](通常是16位,按机器字节顺序)
S – unsigned short (always 16 bit, machine byte order)
S – 不带有符号的短模式[short](通常是16位,按机器字节排序)
n – unsigned short (always 16 bit, big endian byte order)
n -不带有符号的短模式[short](通常是16位,按大endian字节排序)
v – unsigned short (always 16 bit, little endian byte order)
v -不带有符号的短模式[short](通常是16位,按小endian字节排序)
i – signed integer (machine dependent size and byte order)
i – 带有符号的整数(由大小和字节顺序决定)
I – unsigned integer (machine dependent size and byte order)
I – 不带有符号的整数(由大小和字节顺序决定)
l – signed long (always 32 bit, machine byte order)
l– 带有符号的长模式[long](通常是32位,按机器字节顺序)
L – unsigned long (always 32 bit, machine byte order)
L – 不带有符号的长模式[long](通常是32位,按机器字节顺序)
N – unsigned long (always 32 bit, big endian byte order)
N – 不带有符号的长模式[long](通常是32位,按大edian字节顺序)
V – unsigned long (always 32 bit, little endian byte order)
V– 不带有符号的长模式[long](通常是32位,按小edian字节顺序)
f – float (machine dependent size and representation)
f –浮点(由大小和字节顺序决定)
d – double (machine dependent size and representation)
d – 双精度(由大小和字节顺序决定)
x – NUL byte
x – 空字节[NUL byte]
X – Back up one byte
X- 后面一个字节[Back up one byte]
Z 一个空结束的(和空填充的)字节串
@ – NUL-fill to absolute position
@ – NUL- 添加到一个绝对位置[absolute position] //实际使用的时候作为从开头跳到某字节用,很有用
字符串中会出现“\0”,此为C语言的字符串结束符,需要手工将其删掉:
$name = strtok($name, "\0");
例子1:
//从客户端获取二进制流数据按字段长度进行解析
$stream = file_get_contents ( "php://input" );
//用n表示短整型数据s,用N表示整形数据i
$format = "ncode/A64username/Ncount";
$length = 2+64+4;
$getarr = bin2string($stream,$format,$length);
print_r( $getarr);
//二进制流转化成字符串
function bin2string($str,$format,$length){
for($i = 0, $c = strlen($str); $i < $c; $i += $length) {
$arr = unpack("@$i/$format", $str);
foreach($arr as &$value) {
if(is_string($value)) {
$value = strtok($value, "\0");
}
}
}
return $arr;
}
//将数据转化成二进制流发送给客户端
$arr = array("username"=>array('A64',"abc"),
"count"=>array('N',123));
echo string2bin($arr);
//转化成二进制流
function string2bin($arr){
$atArr=array();
foreach ($arr as $k=>$v)
{
$atArr[]=pack($v[0],$v[1]);
}
$stream=join($atArr);
return $stream;
}
//读取二进制文件进行解析
$fp = fopen($file,"rb");
$data = fread($fp,2);
$arr = unpack("n",$data);
print_r($arr);
例子2:
struct BIANBIAN {
char name[10];
char pass[33];
int age;
unsigned char flag;
};
比如有个“kilobug.com”文件,内容就是上面的N个BIANBIAN结构体构成的。读取的php代码:
/* 下面根据struct确定$format,注意int类型跟机器环境有关,我的32位Linux是4个长度 */
$format = 'a10name/a33pass/iage/Cflag';
/* 确定一个struct占用多少长度字节,如果只是读取单个结构体这是不需要的 */
$length = 10 + 33 + 4 + 1;
/* 也可以用fopen + fread + fclose,不过file_get_contents因为可以mmap,效率更高 */
$data = file_get_contents('kilobug.com', 'r');
for ($i = 0, $c = strlen($data); $i < $c; $i += $length) {
$bianbian = unpack("@$i/$format", $data);
/* reference传递是php 5才支持的,如果用php4,得用其他办法 */
foreach ($bianbian as &$value) {
if (is_string($value)) {
$value = strtok($value, "\0");
}
}
print_r($bianbian);
}
/* 输出为array,即类似:*/
Array
(
[name] => 'kilobug'
[pass] => 'kilobug.com'
[age] => 100
[flag] => 0
)