2009-09-02 9 views
3

のは、私がPerlでバイナリファイルからunsigned intを読み取るにはどうすればよいですか?

[unsigned int(length of text)][text][unsigned int(length of text)][text][unsigned int(length of text)][text] 

のようにフォーマットされたバイナリファイルとだけ繰り返し続けているファイルのためにそのパターンを持っているとしましょう。私はどのようにしてunsigned intを読み、それを印刷してPerlのテキストブロックを出力しますか?

この場合も、これはバイナリファイルであり、プレーンテキストファイルではありません。

答えて

2

ここには小さな実例があります。

#!/usr/bin/perl 

use strict; 
use warnings; 

my $INT_SIZE = 2; 
my $filename = 'somefile.bin'; 

open my $fh, '<', $filename or die "Couldn't open file $filename: $!\n"; 

binmode $fh; 

while (read $fh, my $packed_length, $INT_SIZE) { 

    my $text = ''; 
    my $length = unpack 'v', $packed_length; 

    read $fh, $text, $length; 

    print $length, "\t", $text, "\n"; 
} 

変更INT_SIZEと(いずれかの「V」または「n」または「V」または「N」)を合わせてアンパックテンプレートのサイズとエンディアン。詳細については、unpackのマンページを参照してください。

1

データにunpack関数を使用する必要があります。チェックアウト:Pack/Unpack Tutorial (aka How the System Stores Data)

このあなたは(32ビットと仮定して)正しい方向に向かって取得する必要があります。

#!/usr/bin/perl 

use strict; 

my $strBuf = "perl rocks"; 
my $packed = pack("I Z15", length($strBuf), $strBuf); 
{ 
    open(my $binFile, '>', "test.bin") || die("Error opening file\n"); 
    binmode $binFile; 
    print $binFile $packed; 
    close $binFile; 
} 


open(my $binFile, '<', "test.bin") || die("Error opening file\n"); 
binmode $binFile; 

my $buffer; 
read($binFile, $buffer, 4); ## Read out unsigned int binary data 
my $length = unpack("I", $buffer); ## Unpack the data 

read($binFile, $buffer, $length); ## Read the length out as binary 
my $string = unpack("Z$length", $buffer); ## Unpack the string data in buffer 

print "Len: $length String: $string\n"; 
exit; 
+1

あなたのコードでは、Cの 'unsigned int'は4バイトであると仮定しています(これは私が知っているように)。このミックスアップを回避するより良い方法は、ファイル全体を読み込み、それを処理することです。つまり、 'unsigned int 'が2バイトの16ビットプラットフォーム上で動作する場合、コードは正常に動作します。 –

+0

だからこそ私は32ビットと仮定していた。私はメモリに読み込むことは良いと思いますが、おそらく良い解決策であることに同意しますが、処理されているファイルのサイズやマシン上で使用可能なメモリはわかりません。両方の解決策にはピット・フォールがあります。 –

+0

Chrisさん、ファイル全体をメモリに読み込むのは、間違った整数サイズを使用しないでください。 –

0

unpackを使用することに加えて、RCが指摘するように、あなたはほぼ確実にデータを読み出すためにreadまたはsysreadを使用したいと思うでしょうファイルから。

+0

彼は彼の答えを編集しました。 –

0

ここでは、この問題を完全に解決するための十分な情報はありません。

長さフィールドとテキストフィールドの正確なフォーマットが必要です。 int 2バイト、4バイトまたは8バイトですか? (すべて可能です)また、リトルエンディアンかビッグエンディアンですか?

この情報が与えられると、read関数を使用して最初の整数にアクセスし、ビット演算またはアンパック関数を使用して数値に変換します。

次の問題は、テキスト文字列の正確な形式です。それはASCII、EBCDIC、またはUTF形式ですか?これを知ることで、文字列の長さを計算し、1つまたは複数の読み取り操作を使用して、より管理しやすい形式に変換する必要のある生の文字列を取得できます。

バイナリモードでファイルを開く必要があります。そうしないと、期待どおりの結果が得られない場合があります。

+0

私はプラットフォームのデフォルトの 'unsigned int'を' unpack'コードにして、このようなプラットフォームの依存関係に依存できると仮定します。そして、あなたは怠け者で、ファイル全体を読み込んだ後、処理してください。 –

関連する問題