文件除了是二进制流外,其保存的结构和数据类型以及文件定义的保存结构有关。
1、big-endian和little-endian之分,如地址0x3BEF,按big-endian,保存为 3B EF;按little-endian,保存为EF 3B。
2、与数据类型有关。如数值01,按单字节保存为01,按short保存,为00 01;按Long类型保存,为00 00 00 01。
pack——将数值保存成符合文件要求的格式的二进制文件流
pack('k1k2k3k4...',$arg1,$arg2,$arg3,$arg4...)——将$arg1,$arg2,$arg3,$arg4...等数值按K1,K2,K3,K4....的格式转换成二进制流。
K1,K2,K3,K4文件取值如下表
Code | Description |
---|---|
a | NUL-padded string |
A | SPACE-padded string |
h | Hex string, low nibble first,低位优先16进制字符 |
H | Hex string, high nibble first,高位优先16进制字符 |
c | signed char,带符号单字节 |
C | unsigned char,无符号单字节 |
s | signed short (always 16 bit, machine byte order),有符号双字节,顺序按机器设定 |
S | unsigned short (always 16 bit, machine byte order)无符号双字节,顺序按机器设定 |
n | unsigned short (always 16 bit, big endian byte order)无符号双字节,高位优先 |
v | unsigned short (always 16 bit, little endian byte order)无符号双字节,低位优先 |
i | signed integer (machine dependent size and byte order)有符号整数,字节数和顺序按机器设定 |
I | unsigned integer (machine dependent size and byte order)无符号整数,字节数和顺序按机器设定 |
l | signed long (always 32 bit, machine byte order)有符号4字节数,顺序按机器设定 |
L | unsigned long (always 32 bit, machine byte order)无符号4字节数,顺序按机器设定 |
N | unsigned long (always 32 bit, big endian byte order)无符号4字节数,高位优先 |
V | unsigned long (always 32 bit, little endian byte order)无符号4字节数,低位优先 |
q | signed long long (always 64 bit, machine byte order)有符号8字节数,顺序按机器设定 |
Q | unsigned long long (always 64 bit, machine byte order)无符号8字节数,顺序按机器设定 |
J | unsigned long long (always 64 bit, big endian byte order)无符号8字节数,高位优先 |
P | unsigned long long (always 64 bit, little endian byte order)无符号8字节数,低位优先 |
f | float (machine dependent size and representation)浮点数,字节数和顺序按机器设定 |
g | float (machine dependent size, little endian byte order)浮点数,字节数按机器设定,高位优先 |
G | float (machine dependent size, big endian byte order)浮点数,字节数按机器设定,低位优先 |
d | double (machine dependent size and representation)双精度数,字节数和顺序按机器设定 |
e | double (machine dependent size, little endian byte order)双精度数,字节数按机器设定,高位优先 |
E | double (machine dependent size, big endian byte order)双精度数,字节数按机器设定,低位优先 |
x | NUL byte |
X | Back up one byte |
Z | NUL-padded string (new in PHP 5.5) |
@ | NUL-fill to absolute position |
示例:
pack('nnnn',79,79,78,78)=>00 79 00 79 00 78 00 78(为简单,用十进制表示);
pack('cnnN',79,79,78,78)=> 79 00 79 00 78 00 00 00 78;
pack('cnvV',79,79,78,78)=> 79 00 79 78 00 78 00 00 00;
unpack——将二进制文件流按文件结构转换成数值,pack的逆过程
(一)unpack解析
1、用法:
unpack(format,$binary),返回带key的数组。
2、参数format
format由多个数值描述组成,每个描述用'/'表示区分,每个描述由3个参数组成:[type][ number][ key],故format可写成:
[type1][ number1][ key1]/[type2][ number2][ key2]/[type3][ number3][ key3]/....
[type]就是上面的code,代表数据的类型;
[number]表示该类型数据由多少个,可以缺省不写,代表一个;
[key]返回的数组中该数值的key。可以不写没有指定key,自动用1,2,3,取代;如果相同格式的数值使用同一个key,会自动递增key1,key2,key3.....
(二)列举format的写法
1、相同格式的数据流format不同写法
unpack('n*','00 79 00 79 00 78 00 78')=>['1'=>79,'2'=>79,'3'=>78,'4'=>78]//*代表不断循环,直至数据流结束;key按数字1,2,3递增;
unpack('n4','00 79 00 79 00 78 00 78')=>['1'=>79,'2'=>79,'3'=>78,'4'=>78]//提取4个2字节;key按数字1,2,3递增;
unpack('n4data','00 79 00 79 00 78 00 78')=>['data1'=>79,'data2'=>79,'data3'=>78,'data4'=>78]//提取4个2字节;key以data为前缀,按数字1,2,3递增;
unpack('n2data/n2num','00 79 00 79 00 78 00 78')=>['data1'=>79,'data2'=>79,'num3'=>78,'num4'=>78]//前两个2字节;key以data为前缀,按数字1,2,3递增;后2个提取2个字节,以num为前缀,递增;
unpack('n2data/n2data','00 79 00 79 00 78 00 78')=>['data1'=>78,'data2'=>78]//由于后面的前缀和前面两个前缀一致,导致数组中同key被覆盖,所以只返回最后两个数值。
unpack('n2/n2','00 79 00 79 00 78 00 78')=>['1'=>78,'2'=>78]//原因同上。
unpack('nwidth/nheight/ndepth/nfilter','00 79 00 79 00 78 00 78')=>['width'=>79,'height'=>79,'depth'=>78,'filter'=>78]//给每个数值设置不同的key。
2、不同格式的数据流format写法
unpack('n1data/c6num','00 79 00 79 00 78 00 78')=>['data1'=>79,'num1'=>00,'num2'=>79,'num3'=>00,'num4'=>78,'num5'=>00,'num6'=>78];
unpack('ndata/c/cnum/cwidth/cheight/c2tt','00 79 00 79 00 78 00 78')=>['data'=>79,'1'=>00,'num'=>79,'width'=>00,'height'=>78,'tt1'=>00,'tt2'=>78];