2

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は関係ありません。ありがとう!!!!

4

2 に答える 2

6

ここでは、読んでいるデータのエンディアンが重要です。2つのロングがリトルエンディアンの順序で格納されているため、8オクテットを開梱しているようです。それが単一の64ビット量ではないことを確認しますか(qまたはQフォーマットがより適切になります)?残念ながら、私は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;
于 2012-06-28T23:53:41.577 に答える
2

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 != ""この場合、が慣用的なループであるかどうかはわかりません。大きなチャンクを読み込んで、関心のあるバイトのみを解析することをお勧めします。OSレベルのread()操作は非常に遅く、半分にカットすると、アプリケーションの速度が約2倍になります。はるかに大きなデータブロックの読み取りに変更すると、間違いなくさらに大きなスピードアップが得られる可能性がありますが、この小さな変更よりも多くの書き換えが必要になる場合があります。

于 2012-06-28T22:35:17.427 に答える