2013-03-19 58 views
0

我正在讀取一個二進制文件格式,它以4個常量校驗字節開始,後面跟着3個八位字節,表示記錄的數據部分將會有多長。我可以解碼如下:在Perl中解碼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

回答

1

不,unpack不支持3字節(或任意長度)的整數,但你可以使用一個16位無符號大端INT節省一點工作:

my ($type, $l1, $l23) = unpack("a4 Cn", $x); 
my $length = $l1 << 16 | $l23; 
+0

聽起來很不錯,謝謝。 – 2013-03-20 03:08:27

2

你可以插入空字節到以字符串能夠使用「N」格式:

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

編輯:要不解開兩個步驟:

my ($type, $length) = unpack "a4 a3", $x; 
$length = unpack "N", "\0" . $length; 
1

解決方案:獲取類型的方法很好。但是,我建議您將長度分開解壓爲一個四字節整數,然後丟棄這四個字節的第一個字節。即使它重疊並丟棄類型的最後一個字節,它也會更有效。

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 
+0

很酷。如果我需要更好的表現,我會把它放在我的後兜裏 - 可能會混淆下一個人(可能是我未來的自我)。 – 2013-03-20 03:07:51

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");