ZetCode

Perl pack 函数

最后修改于 2025 年 4 月 4 日

Perl 的 pack 函数将数据转换为二进制表示。它对于二进制文件 I/O、网络协议和数据序列化至关重要。

pack 使用模板字符串指定数据格式。它根据模板返回包含打包数据的二进制字符串。对应的函数是用于反向操作的 unpack

基本 pack 用法

pack 最简单的用法是将数字转换为二进制字符串。

basic.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $packed = pack("C", 65);
print "Packed ASCII 'A': ", unpack("H*", $packed), "\n";

my $packed_short = pack("s", 12345);
print "Packed short: ", unpack("H*", $packed_short), "\n";

我们演示了打包一个字符和一个短整数。“C”模板打包无符号字符,“s”打包短整数。我们使用 unpack 来显示十六进制表示。

$ ./basic.pl
Packed ASCII 'A': 41
Packed short: 3930

打包多个值

pack 可以将多个值合并到一个二进制字符串中。

multiple.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $data = pack("CCCC", 65, 66, 67, 68);
print "Packed ABCD: ", unpack("H*", $data), "\n";

my $mixed = pack("CS", 65, 12345);
print "Packed mixed: ", unpack("H*", $mixed), "\n";

此示例打包了四个字符和一种混合格式。模板字符串指定了要打包的数据的顺序和类型。每个格式字符处理参数列表中的一个值。

$ ./multiple.pl
Packed ABCD: 41424344
Packed mixed: 413930

字符串打包

pack 可以处理具有各种格式选项的字符串。

string.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $str = "Perl";
my $packed_str = pack("a4", $str);
print "Packed string: ", unpack("H*", $packed_str), "\n";

my $null_terminated = pack("Z*", $str);
print "Null-terminated: ", unpack("H*", $null_terminated), "\n";

我们演示了使用“a”(空格填充)和“Z”(null 终止)格式的 ASCII 字符串打包。星号 (*) 允许可变长度字符串。

$ ./string.pl
Packed string: 5065726c
Null-terminated: 5065726c00

网络字节序

网络协议通常需要特定的字节序。

network.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $port = 80;
my $ip = "192.168.1.1";

my $packed_port = pack("n", $port);
my @octets = split /\./, $ip;
my $packed_ip = pack("C4", @octets);

print "Packed port: ", unpack("H*", $packed_port), "\n";
print "Packed IP: ", unpack("H*", $packed_ip), "\n";

这显示了网络字节序(“n”表示大端短整数)和 IP 地址打包。网络协议通常使用大端字节序。

$ ./network.pl
Packed port: 0050
Packed IP: c0a80101

二进制文件写入

pack 对于写入二进制文件至关重要。

file.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $filename = "data.bin";
open(my $fh, '>', $filename) or die "Cannot open file: $!";

my $header = pack("a4LL", "DATA", 1, 12345);
print $fh $header;

close($fh);
print "Wrote binary file '$filename'\n";

我们创建了一个带有标题结构的简单二进制文件。模板“a4LL”打包一个 4 字节字符串,后跟两个无符号长整数。这在二进制文件格式中很常见。

$ ./file.pl
Wrote binary file 'data.bin'

浮点数

pack 可以处理各种格式的浮点数。

float.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $float = 3.14159;
my $packed_float = pack("f", $float);
my $packed_double = pack("d", $float);

print "Packed float: ", unpack("H*", $packed_float), "\n";
print "Packed double: ", unpack("H*", $packed_double), "\n";

这演示了将浮点数打包为 32 位(“f”)和 64 位(“d”)值。确切的十六进制输出取决于您系统的浮点表示。

$ ./float.pl
Packed float: d00f4940
Packed double: 6e861bf0f9210940

复杂数据结构

pack 可以创建具有重复的复杂二进制结构。

complex.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my @values = (1..5);
my $packed = pack("L5", @values);

print "Packed array: ", unpack("H*", $packed), "\n";

my $struct = pack("LSZ8", 12345, 3.14, "Perl");
print "Packed struct: ", unpack("H*", $struct), "\n";

我们打包了一个长整数数组和一个混合结构。“L5”中的“5”将长整数格式重复了五次。复杂的二进制协议通常使用此类结构。

$ ./complex.pl
Packed array: 0100000002000000030000000400000005000000
Packed struct: 39300000c3f54840Perl00

最佳实践

来源

Perl pack 文档

本教程介绍了 Perl 的 pack 函数,并通过实际示例演示了各种场景下的二进制数据转换。

作者

我的名字是 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Perl 教程