pack

(PHP 4, PHP 5, PHP 7, PHP 8)

pack将数据打包成二进制字符串

描述

pack(string $format, mixed ...$values): string

根据 format 将给定的参数打包成二进制字符串。

此函数的理念来自 Perl,所有格式代码的工作方式与 Perl 中相同。但是,某些格式代码缺失,例如 Perl 的“u”格式代码。

请注意,有符号和无符号值之间的区别仅影响 unpack() 函数,而 pack() 函数对有符号和无符号格式代码给出相同的结果。

参数

format

format 字符串由格式代码和可选的重复器参数组成。重复器参数可以是整数值或 *,用于重复到输入数据的末尾。对于 a、A、h、H,重复计数指定从一个数据参数中获取多少个字符,对于 @,它是在何处放置下一个数据的绝对位置,对于其他所有情况,重复计数指定消耗和打包到结果二进制字符串中的数据参数数量。

当前已实现的格式为

pack() 格式字符
代码 描述
a 以 NUL 填充的字符串
A 以空格填充的字符串
h 十六进制字符串,低位字节在前
H 十六进制字符串,高位字节在前
c有符号字符
C 无符号字符
s 有符号短整型(始终为 16 位,机器字节序)
S 无符号短整型(始终为 16 位,机器字节序)
n 无符号短整型(始终为 16 位,大端字节序)
v 无符号短整型(始终为 16 位,小端字节序)
i 有符号整型(机器相关的尺寸和字节序)
I 无符号整型(机器相关的尺寸和字节序)
l 有符号长整型(始终为 32 位,机器字节序)
L 无符号长整型(始终为 32 位,机器字节序)
N 无符号长整型(始终为 32 位,大端字节序)
V 无符号长整型(始终为 32 位,小端字节序)
q 有符号长长整型(始终为 64 位,机器字节序)
Q 无符号长长整型(始终为 64 位,机器字节序)
J 无符号长长整型(始终为 64 位,大端字节序)
P 无符号长长整型(始终为 64 位,小端字节序)
f 浮点数(机器相关的尺寸和表示)
g 浮点数(机器相关的尺寸,小端字节序)
G 浮点数(机器相关的尺寸,大端字节序)
d 双精度浮点数(机器相关的尺寸和表示)
e 双精度浮点数(机器相关的尺寸,小端字节序)
E 双精度浮点数(机器相关的尺寸,大端字节序)
x NUL 字节
X 后退一个字节
Z 以 NUL 填充的字符串
@ 用 NUL 填充到绝对位置

values

返回值

返回包含数据的二进制字符串。

变更日志

版本 描述
8.0.0 此函数不再在失败时返回 false
7.2.0 floatdouble 类型支持大端和小端。
7.0.15,7.1.1 添加了“e”、“E”、“g”和“G”代码,以支持浮点数和双精度浮点数的字节序。

示例

示例 #1 pack() 示例

<?php
$binarydata
= pack("nvc*", 0x1234, 0x5678, 65, 66);
?>

生成的二进制字符串将是 6 个字节长,包含字节序列 0x12、0x34、0x78、0x56、0x41、0x42。

注释

警告

请注意,PHP 在内部将 int 值存储为机器相关的尺寸的有符号值(C 类型 long)。整型字面量和产生超出 int 类型范围的数字的操作将被存储为 float。将这些浮点数打包为整型时,它们首先被强制转换为整型类型。这可能会或可能不会导致所需的字节模式。

最相关的情况是打包如果 int 类型是无符号的,则可以用 int 类型表示的无符号数字。在 int 类型具有 32 位尺寸的系统中,强制转换通常会导致与 int 为无符号时相同的字节模式(尽管这依赖于根据 C 标准进行的实现定义的无符号到有符号转换)。在 int 类型具有 64 位尺寸的系统中,float 最有可能没有足够大的尾数来保存该值而不会丢失精度。如果这些系统也有本地的 64 位 C int 类型(大多数类 UNIX 系统都没有),那么在较高范围内使用 I 打包格式的唯一方法是创建具有与所需无符号值相同的字节表示的 int 负值。

参见

  • unpack() - 从二进制字符串中解包数据

添加注释

用户贡献的注释 10 个注释

chadm at codeangel dot org
12 年前
如果您想了解 pack/unpack。这里有一个 perl 的教程,它在理解 php 的 pack/unpack 方面同样有效

https://perldoc.perl5.cn/perlpacktut.html
stanislav dot eckert at vizson dot de
8 年前
一个辅助类,用于将整型转换为二进制字符串,反之亦然。这对于写入和读取文件或套接字中的整型很有用。

<?php

class int_helper
{
public static function
int8($i) {
return
is_int($i) ? pack("c", $i) : unpack("c", $i)[1];
}

public static function
uInt8($i) {
return
is_int($i) ? pack("C", $i) : unpack("C", $i)[1];
}

public static function
int16($i) {
return
is_int($i) ? pack("s", $i) : unpack("s", $i)[1];
}

public static function
uInt16($i, $endianness=false) {
$f = is_int($i) ? "pack" : "unpack";

if (
$endianness === true) { // 大端序
$i = $f("n", $i);
}
else if (
$endianness === false) { // 小端序
$i = $f("v", $i);
}
else if (
$endianness === null) { // 机器字节序
$i = $f("S", $i);
}

return
is_array($i) ? $i[1] : $i;
}

public static function
int32($i) {
return
is_int($i) ? pack("l", $i) : unpack("l", $i)[1];
}

public static function
uInt32($i, $endianness=false) {
$f = is_int($i) ? "pack" : "unpack";

if (
$endianness === true) { // 大端序
$i = $f("N", $i);
}
else if (
$endianness === false) { // 小端序
$i = $f("V", $i);
}
else if (
$endianness === null) { // 机器字节序
$i = $f("L", $i);
}

return
is_array($i) ? $i[1] : $i;
}

public static function
int64($i) {
return
is_int($i) ? pack("q", $i) : unpack("q", $i)[1];
}

public static function
uInt64($i, $endianness=false) {
$f = is_int($i) ? "pack" : "unpack";

if (
$endianness === true) { // 大端序
$i = $f("J", $i);
}
else if (
$endianness === false) { // 小端序
$i = $f("P", $i);
}
else if (
$endianness === null) { // 机器字节序
$i = $f("Q", $i);
}

return
is_array($i) ? $i[1] : $i;
}
}
?>

使用示例
<?php
Header
("Content-Type: text/plain");
include(
"int_helper.php");

echo
int_helper::uInt8(0x6b) . PHP_EOL; // k
echo int_helper::uInt8(107) . PHP_EOL; // k
echo int_helper::uInt8("\x6b") . PHP_EOL . PHP_EOL; // 107

echo int_helper::uInt16(4101) . PHP_EOL; // \x05\x10
echo int_helper::uInt16("\x05\x10") . PHP_EOL; // 4101
echo int_helper::uInt16("\x05\x10", true) . PHP_EOL . PHP_EOL; // 1296

echo int_helper::uInt32(2147483647) . PHP_EOL; // \xff\xff\xff\x7f
echo int_helper::uInt32("\xff\xff\xff\x7f") . PHP_EOL . PHP_EOL; // 2147483647

// 注意:使用 64 位版本的 PHP 进行测试
echo int_helper::uInt64(9223372036854775807) . PHP_EOL; // \xff\xff\xff\xff\xff\xff\xff\x7f
echo int_helper::uInt64("\xff\xff\xff\xff\xff\xff\xff\x7f") . PHP_EOL . PHP_EOL; // 9223372036854775807

?>
plutus at gmx dot de
24 年前
请注意,在 Perl 中,上面的命令看起来像这样

$binarydata = pack ("n v c*", 0x1234, 0x5678, 65, 66);
在 PHP 中,第一个参数似乎不允许空格。 因此,如果您想将 Perl 的 pack 命令转换为 PHP,请不要忘记删除空格!
FrozenFire
13 年前
如果您需要从大端序或小端序中解包一个有符号的短整型,而不是机器字节序,您只需将其解包为无符号形式,然后如果结果 >= 2^15,则从中减去 2^16。

一个例子是

<?php
$foo
= unpack("n", $signedbigendianshort);
$foo = $foo[1];
if(
$foo >= pow(2, 15)) $foo -= pow(2, 16);
?>
j.s.hoekstra
18 年前
/* 将浮点数从主机序转换为网络序 */
function FToN( $val )
{
$a = unpack("I",pack( "f",$val ));
return pack("N",$a[1] );
}

/* 将网络字节序的浮点数转换为主机字节序 */
function NToF($val )
{
$a = unpack("N",$val);
$b = unpack("f",pack( "I",$a[1]));
return $b[1];
}
php at nagler-ihlein dot de
16 年前
注意格式代码 H 总是对字节对齐进行填充 0(对于奇数个半字节)。

因此 pack("H", "7") 会生成 0x70(ASCII 字符 'p'),而不是 0x07(响铃字符)
以及 pack("H*", "347") 会生成 0x34 ('4') 和 0x70 ('p'),而不是 0x03 和 0x47。
Patrik Fimml
18 年前
您将使用以下方法获得相同的效果

<?php
function _readInt($fp)
{
return
unpack('V', fread($fp, 4));
}
?>

或 unpack('N', ...) 用于大端字节序。
petepostma at gmail dot spam dot com
12 年前
即使在 64 位架构中 intval(6123456789) = 6123456789,而 sprintf('%b', 5000000000) = 100101010000001011111001000000000
pack 不会将传递给它的任何内容视为 64 位。如果您想打包一个 64 位整数

<?php
$big
= 5000000000;

$left = 0xffffffff00000000;
$right = 0x00000000ffffffff;

$l = ($big & $left) >>32;
$r = $big & $right;

$good = pack('NN', $l, $r);

$urlsafe = str_replace(array('+','/'), array('-','_'), base64_encode($good));

//done!

//rebuild:
$unurl = str_replace(array('-','_'), array('+','/'), $urlsafe);
$binary = base64_decode($unurl);

$set = unpack('N2', $tmp);
print_r($set);

$original = $set[1] << 32 | $set[2];
echo
$original, "\\r\\n";
?>

结果是
数组
(
[1] => 1
[2] => 705032704
)
5000000000

但仅在支持 64 位的机器和 PHP 发行版上。
Ammar Hameed
14 年前
使用 pack 将阿拉伯字符写入文件。

<?php
$text
= "&#13574;&#13830;&#13830;";

$text = mb_convert_encoding($text, "UCS-2BE", "HTML-ENTITIES");

$len = mb_strlen($text);

$bom = mb_convert_encoding("&#65534;", "unicode", "HTML-ENTITIES");

$fp = fopen('text.txt', 'w');

fwrite($fp, pack('a2', $bom));
fwrite($fp, pack("a{$len}", $text));
fwrite($fp, pack('a2', $bom));
fwrite($fp, pack('a2', "\n"));

fclose($fp);
?>
ru
7 年前
pack()
h 十六进制字符串,低半字节优先(与 hex2bin() 不相同)
H 十六进制字符串,高半字节优先(与 hex2bin() 相同)
To Top