在Perl中,可以将字符串视为字节数组吗?
在Perl中,使用字符串作为包含8位数据的字节数组是否合适?我能找到的关于这个主题的所有文档都集中在7位字符串上 例如,如果我将一些数据从二进制文件读入在Perl中,可以将字符串视为字节数组吗?,perl,string,binary,Perl,String,Binary,在Perl中,使用字符串作为包含8位数据的字节数组是否合适?我能找到的关于这个主题的所有文档都集中在7位字符串上 例如,如果我将一些数据从二进制文件读入$data my $data; open FILE, "<", $filepath; binmode FILE; read FILE $data 1024; my$data; 打开文件,“您可能想使用,如果您想从二进制文件中读取字节 另见 这是适当的还是必要的取决于你到底想做什么 #!/usr/bin/perl -l use stri
$data
my $data;
open FILE, "<", $filepath;
binmode FILE;
read FILE $data 1024;
my$data;
打开文件,“您可能想使用,如果您想从二进制文件中读取字节
另见
这是适当的还是必要的取决于你到底想做什么
#!/usr/bin/perl -l
use strict; use warnings;
use autodie;
use Fcntl;
sysopen my $bin, 'test.png', O_RDONLY;
sysread $bin, my $header, 4;
print map { sprintf '%02x', ord($_) } split //, $header;
输出:
C:\Temp> t
89504e47
C:\Temp>t
89504e47此处复制的read
命令的捆绑文档提供了许多与您的问题相关的信息
读取文件句柄、标量、长度、偏移量
读取文件句柄,标量,长度
尝试将数据的长度字符读入变量标量
从指定的文件句柄。返回
实际读取的字符,文件末尾为0,如果有,则为未定义字符
是一个错误(在后一种情况下,还设置了$!)。标量将
放大或缩小,使最后一个实际读取的字符
读取后标量的最后一个字符
可以指定偏移量以将读取的数据放置在某个位置
在字符串中,而不是在开头。负偏移量
指定向后计数的多个字符的位置
从字符串末尾开始。大于
标量的长度导致字符串填充到
读取结果之前所需的大小为“\0”字节
附加
该调用实际上是根据Perl或
系统的fread()调用。要获得真正的读取(2)系统调用,请参阅
“系统读取”
注意字符:根据文件句柄的状态,
读取(8位)字节或字符。默认情况下为所有
filehandles对字节进行操作,但例如,如果filehandle
已使用“:utf8”I/O层打开(请参阅“打开”,并且
“打开”pragma,open),I/O将在UTF-8编码上运行
Unicode字符,而不是字节。与“:编码”类似
pragma:在这种情况下,几乎可以读取任何字符
有关如何将字符串视为字节数组的信息,请参见和。如果您告诉我们如何使用字节数组,可能会有更多帮助。处理二进制数据有多种方法,每种方法都适用于不同的工具集
是否要将数据转换为Perl数组?如果是这样,pack
和unpack
是一个很好的开始。split
也可以派上用场
是否要在不解压缩的情况下访问字符串的各个元素?如果是这样,substr
速度很快,可以处理8字节数据。如果需要其他位深度,请查看vec
函数,该函数将字符串作为位向量处理
您想扫描字符串并将某些字节转换为其他字节吗?然后s//
或tr//
结构可能会有用。请允许我发布一个关于将字符串视为二进制数组的小示例,因为我自己发现很难相信称为“substr”的东西“将处理空字节;但看起来确实如此-下面是perl调试器终端会话的一个片段(使用字符串和数组/列表方法):
$perl-d
从perl5db.pl版本1.32加载数据库例程
编辑器支持可用。
输入h或“h”以获取帮助,或输入“man perldebug”以获取更多帮助。
^D
已调试程序已终止。使用q退出,或使用R重新启动,
使用o inhibit_exit避免程序终止后停止,
h q、h R或h o以获取其他信息。
DB$str=“\x00\x00\x84\x00”
DB打印$str
�
DB print unpack(“H*”,$str)#通过“unpack”将$str的内容显示为十六进制`
00008400
DB$str2=substr($str,2,2)
DB打印解包(“H*”,$str2)
8400
DB$str2=substr($str,1,3)
DB打印解包(“H*”,$str2)
008400
[...]
DB@stra=分割(“”,$str);打印@stra#将字符串转换为数组(在空字符串处拆分)
�
DB打印解包(“H*”,$stra[3])#独立打印。元素。数组的十六进制形式
00
DB打印解包(“H*”,$stra[2])
84
DB打印解包(“H*”,$stra[1])
00
DB打印解包(“H*”,$stra[0])
00
DB print unpack(“H*”,join(“”,@stra[1..3])#通过索引只打印数组/列表的一部分(使用触发器[两点]操作符)
008400
字符串是大于一个字节的“字符”字符串。您可以将字节存储在它们中,并像处理字符一样对它们进行操作,获取它们的substr
s等等,只要您只是在处理内存中的实体,一切都非常美好。数据存储很奇怪,但这绝不是你的问题
当您尝试读取和写入文件时,字符可能不会映射到字节这一事实变得非常重要和有趣。更不用说烦人了。Perl试图在常见情况下执行您想要的操作,这实际上会使这种烦恼变得更糟:如果字符串中的所有字符都适合一个字节,而您恰好在非Windows操作系统上,那么您实际上不必执行任何特殊的读写字节操作。然而,如果您存储了一个非字节大小的字符,并试图编写它,而没有给出如何处理它的线索,Perl就会抱怨
这有点离题了,主要是因为编码是一个大而混乱的话题。让我在这里留下一些参考资料:看看、、和,有很多搞笑和血腥的细节
因此,总结答案是“是的,如果字符串实际上包含字节,那么可以将字符串视为包含字节,而这只能通过读取和写入字节来保证。”
:或迂腐地说,“虽然它可以表示比字节更大的值范围
$ perl -d
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
^D
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1> $str="\x00\x00\x84\x00"
DB<2> print $str
�
DB<3> print unpack("H*",$str) # show content of $str as hex via `unpack`
00008400
DB<4> $str2=substr($str,2,2)
DB<5> print unpack("H*",$str2)
8400
DB<6> $str2=substr($str,1,3)
DB<7> print unpack("H*",$str2)
008400
[...]
DB<30> @stra=split('',$str); print @stra # convert string to array (by splitting at empty string)
�
DB<31> print unpack("H*",$stra[3]) # print indiv. elems. of array as hex
00
DB<32> print unpack("H*",$stra[2])
84
DB<33> print unpack("H*",$stra[1])
00
DB<34> print unpack("H*",$stra[0])
00
DB<35> print unpack("H*",join('',@stra[1..3])) # print only portion of array/list via indexes (using flipflop [two dots] operator)
008400
use Devel::Peek;
my $x = "bluh bluh bluh bluh";
Dump($x);
$x =~ /bluh/mg;
Dump($x);
$x =~ /bluh/mg;
Dump($x);