簡體   English   中英

如何從二進制文件中讀取塊並使用Python或Perl使用unpack提取結構?

[英]How can I read a block from a binary file and extract structs using unpack using Python or 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 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;

我想我每循環讀取52個字節( 24+28==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()操作非常慢,將它們減少一半將大約是應用程序速度的兩倍。 如果你改為閱讀更大的數據塊,你肯定可以獲得更大的加速 - 但這可能需要比這個微小的改變更多的重寫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM