2013-03-08 43 views
2

我有一个需要解析的二进制文件。我正在做的是指定一个偏移量,然后让程序返回该位置的字节值。Perl - 解析二进制文件并返回指定偏移量的值

我不确定的是如何去做这件事。我有文件打开的部分,但我不知道如何让程序跳转到该位置。

任何帮助,将不胜感激。

谢谢。

+0

你可以展示你到目前为止尝试过的吗? – gpojd 2013-03-08 16:42:53

+2

['perldoc -f seek'](http://search.cpan.org/perldoc?perlfunc#seek) – mob 2013-03-08 16:47:14

+0

我在寻找寻找,但我不知道该怎么处理它。我是否有进入一个变量打印或我需要别的东西来真正拉动我们的字节数据? – 2013-03-08 16:50:20

回答

5
use Fcntl qw(:seek); 

my($fh, $filename, $byte_position, $byte_value); 

$filename  = "/some/file/name/goes/here"; 
$byte_position = 42; 

open($fh, "<", $filename) 
    || die "can't open $filename: $!"; 

binmode($fh) 
    || die "can't binmode $filename"; 

sysseek($fh, $byte_position, SEEK_CUR) # NB: 0-based 
    || die "couldn't see to byte $byte_position in $filename: $!"; 

sysread($fh, $byte_value, 1) == 1 
    || die "couldn't read byte from $filename: $!"; 

printf "read byte with ordinal value %#02x at position %d\n", 
    ord($byte_value), $byte_position; 
+1

tchrist,你太棒了。这正是我需要的。 – 2013-03-08 17:12:31

+0

你可以依靠并教授autodie并将SLOC减半。 https://rt.cpan.org/Public/Bug/Display.html?id=54777已修复。 – daxim 2013-03-09 18:57:21

+2

@daxim只有当你真的很小心地每次写'use autodie v2.12'时,我都不太相信别人去做,也没有。请记住,这必须在基本的供应商Perl安装上运行。我也担心人们没有那些剪辑片断,在这种情况下,他们真的很麻烦。这是一个非常可爱的功能,但你必须非常小心这样的建议。 – tchrist 2013-03-09 19:26:44

1

使用seekFcntl模块方便常数为

#! /usr/bin/env perl 

use bytes; 
use strict; 
use warnings; 

use Fcntl ':seek'; 

open my $fh, "<", $0 or die "$0: open: $!"; 

seek $fh, 0, SEEK_END or die "$0: seek: $!"; 

my $last = tell $fh; 
die "$0: tell: $!" if $last < 0; 

for (1 .. 20) { 
    my $offset = int rand($last + 1); 
    seek $fh, $offset, SEEK_SET or die "$0: seek: $!"; 
    defined read $fh, my $byte, 1 or die "$0: read: $!"; 
    $byte = "\\$byte" if $byte eq "'" || $byte eq "\\"; 
    printf "offset %*d: \\x%02x%s\n", 
     length $last, $offset, 
     unpack("C", $byte), 
     $byte =~ /[[:print:]]/a ? " '$byte'" : ""; 
} 
__DATA__ 
      
: ℞:  
          
             
¡ƨdləɥ ƨᴉɥʇ ədoɥ puɐ ʻλɐp əɔᴉu ɐ əʌɐɥ ʻʞɔnl poo⅁ 

输出示例:

offset 47: \x65 'e' 
offset 392: \x20 ' ' 
offset 704: \xf0 
offset 427: \x5c '\'' 
offset 524: \x61 'a' 
offset 1088: \x75 'u' 
offset 413: \x20 ' ' 
offset 1093: \xbb 
offset 1112: \xc9 
offset 377: \x24 '$' 
offset 64: \x46 'F' 
offset 361: \x62 'b' 
offset 898: \xf0 
offset 566: \x5d ']' 
offset 843: \xf0 
offset 1075: \xc9 
offset 280: \x20 ' ' 
offset 3: \x2f '/' 
offset 673: \x8a 
offset 153: \x20 ' '

__DATA__部分从Tom’s excellent suggestions被借来用于处理UTF的内容-8在Perl程序中。

+1

可能不应该将这些字节打印为字符:您不知道编码。此外,如果您将PERL_UNICODE设置为S中的某个内容,Perl会将它们视为代码点,并最终可能会写出多个字节,您认为您只获得了1个字符。 – tchrist 2013-03-08 17:14:14

+0

@tchrist公平点;更新。 – 2013-03-09 21:12:42