0

私は、4つの定数チェックバイトで始まり、その後にレコードのデータ部分の長さを示す3つのオクテットが続くバイナリファイル形式を読んでいます。私はこれを次のようにデコードできます:

read($fh, $x, 7) or do {
  last if eof;
  die "Can't read: $!";
};
my ($type, $l1, $l2, $l3) = unpack("a4 C3", $x);
my $length = $l1 << 16 | $l2 << 8 | $l3;

中間変数を使用せずに、その3バイト値を読み取るより直接的な方法はありますか?pack仕様に欠けているものがあるのでは?私はpack、16進符号化やその他の気まぐれな追求を除いて、あまり使用していません。

4

4 に答える 4

2

「N」形式を使用できるようにするために、文字列にnullバイトを挿入できます。

substr($x, 4, 0, "\0");
my ($type, $length) = unpack "a4 N", $x;

編集:または、2つのステップで解凍します:

my ($type, $length) = unpack "a4 a3", $x;
$length = unpack "N", "\0" . $length;
于 2013-03-19T23:27:30.883 に答える
2
my $type = unpack("a4", $x);
my $len  = unpack("N", "\0".substr($x, 4));

また

my ($type, $plen) = unpack("a4 a3", $x);
my $len = unpack("N", "\0$plen");
于 2013-03-20T01:11:53.537 に答える
1

いいえ、unpack3バイト(または任意の長さ)の整数をサポートしていませんが、符号なし16ビットビッグエンディアンintを使用して、少しの作業を節約できます。

my ($type, $l1, $l23) = unpack("a4 Cn", $x);
my $length = $l1 << 16 | $l23;
于 2013-03-19T23:24:37.470 に答える
1

解決策:型を取得する方法は問題ありません。ただし、長さを4バイト整数として個別に解凍してから、それらの4バイトの最初のバイトを破棄することをお勧めします。これは、タイプの最後のバイトをオーバーラップして破棄する場合でも、より効率的です。

my $type = unpack("a4", $x);
my $length = unpack("x3N", $x); # skips the first 3 bytes of your original 7-byte string
$length = $length & 0xFFFFFF; # returns only the last 3 bytes of the four-byte integer
于 2013-03-20T00:35:23.130 に答える