如何从二进制文件中读取块并使用 Python 或 Perl 进行解压缩提取结构



我有一个二进制文件,其中包含 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()

这是标题后的外观。

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

如果你们能帮忙,请。Python 或 PERL 无关紧要。谢谢!!!!

您正在阅读的数据的字节序在这里很重要。您似乎正在将 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 filen" 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;
我想

我会在每个循环(24+28==52)读取52字节,然后简单地索引到您关心的字节中。它看起来像这样:

byte = f.read(52)
while byte != "":   
    ticks = struct.unpack("<ll",byte[0:8])
    tocks = struct.unpack("<ll",byte[28:36])
    byte = f.read(52)

请注意,我不知道while byte != ""是否是这种情况的惯用循环。我只是建议阅读更大的块,只解析你感兴趣的字节。操作系统级别的read()操作非常慢,将它们减半大约会使应用程序的速度翻倍。如果你改变读取更大的数据块,你肯定可以获得更大的加速 - 但这可能需要比这个微小的改变更多的重写。

最新更新