如何从二进制文件中读取块并使用Python或Perl使用unpack提取结构?

Nik*_*l S 2 python perl struct unpack

我有一个二进制文件,其中包含4 KB的头信息,然后是28个字节的数据,然后是24个字节,我想要读取.我如何循环每24和28字节并读取(或提取)那28和24字节的每个前8字节数据..在python我做了类似的事情.不知道如何做可变长度

import sys
import struct
f = open(sys.argv[1],"rb")
f.seek(4096)
byte = f.read(28)
while byte != "":   
    ticks = struct.unpack("<ll",byte[:8]) #not sure how to read 8 bytes 
    byte = f.read(28)
f.close()
Run Code Online (Sandbox Code Playgroud)

这是标题后的样子.

Length
(bytes) Field Name
8   TS_INCR
4   SEQID
2   OP
2   LUN
4   NBLKS
8   LBA


Length
(bytes) Field Name
8   TS_INCR
4   SEQID
2   OP
2   LUN
4   LATENCY_TICKS
2   HOST_ID
2   HOST_LUN
Run Code Online (Sandbox Code Playgroud)

如果你们可以帮忙解决这个问题.Python或PERL并不重要.谢谢!!!!

Sin*_*nür 6

您正在阅读的数据的字节顺序非常重要.你似乎正在解压缩8个八位组,因为两个长点以小端顺序存储.您确定它不是一个64位数量(这会使格式qQ格式更合适)吗?不幸的是,我在32位机器上,所以我perl不支持Q.

但是,以下内容应指向正确的方向:

#!/usr/bin/env perl

use strict; use warnings;
use autodie;

use Fcntl qw(:seek);
use List::Util qw( sum );

my ($input_file) = @ARGV;
die "Need input file\n" unless defined $input_file;

my $HEADER_SIZE = 4_096;

my @typedef = (
    {
        fields => [
            qw(
                TS_INCR_LO
                TS_INCR_HI
                SEQID
                OP
                LUN
                NBLKS
                LBA_LO
                LBA_HI
            )
        ],
        tmpl => 'LLLSSLLL',
        start => 0,
        size => 28,
    },
    {
        fields => [
            qw(
                TS_INCR_LO
                TS_INCR_HI
                SEQID
                OP
                LUN
                LATENCY_TICKS
                HOST_ID
                HOST_LUN
            )
        ],
        tmpl => 'LLLSSLSS',
        start => 28,
        size => 24,
    },
);

open my $input, '<:raw', $input_file;

seek $input, $HEADER_SIZE, SEEK_SET;

my $BLOCK_SIZE = sum map $_->{size}, @typedef;
read $input, my($buffer), $BLOCK_SIZE;

my @structs;

for my $t ( @typedef ) {
    my %struct;
    @struct{ @{ $t->{fields}} } = unpack(
        $t->{tmpl},
        substr($buffer, $t->{start}, $t->{size})
    );
    push @structs, \%struct;
}

use Data::Dumper;
print Dumper \@structs;
Run Code Online (Sandbox Code Playgroud)