質問: unpack('H*', $buf); for my $i (0..$#ascii){ if ( $#ascii eq $identifier ){ # .... } } ``` ここまでやりました。 教えていただきたい事は + バイナリデータとアスキーデータの比較 + バイナリデータの削除(これはバイナリ出力時に読み飛ばせばいいかな) + バイナリデータのシーク の3つを教えてください。 よろしくお願いします。
回答: unpackしないほうが楽そうだったので、readで少しずつ読みながら基本バイナリのままで処理してみました。 エラー処理など細かいところは省略してます。 なお、シークするにはそのまま`seek`という関数があるのでこれでシークできます(以下のコードでは使ってませんが)。 ``` use strict; { open(my $in, "<:raw", $ARGV[0]) or die $!; # DCAAまで読み飛ばす my $last_4byte; read($in,$last_4byte,4); #readの戻り値チェックは省略 while( $last_4byte ne "DCAA" ){ # 1byte捨てて1byte読む $last_4byte = substr($last_4byte,1); if ( read($in,$last_4byte,1,3) < 1 ) { die "Not found."; } } # resultとcommand_id、command_idチェック my $result; my $command_id; read($in,$result,2); read($in,$command_id,2); if ( $command_id ne "\x02\x02" ) { die "No JPEG."; #読み飛ばしは省略、後ろで$data捨てれば良い } # length my $length; read($in,$length,4); my $length_val = unpack("N", $length); # 符号無し4バイト整数、ビッグエンディアン # data my $data; read($in,$data,$length_val); #必要なところだけ出力 open(my $out, ">:raw", $ARGV[1]) or die $!; print $out $data; close($out); #繰り返し省略 close($in); } ``` それから、この部分ですが、 > > > ``` > # 16進バイナリ から 文字列 への変換 > my @ascii = unpack('H*', $buf); > ``` > > このコメントは不正確で、正しくはバイナリを16進数文字列に変換します(1バイトが16進数2文字になる)。 要素数は1になるので、後ろのループは1回しか回らないですね。 ``` my $hex_str = unpack('H*', "123"); if ( $hex_str eq "313233" ) { print "Match!\n"; } #これだと各バイトを数値にした配列が得られる my @bytes = unpack('C*', "123"); if ( $bytes[0] == 0x31 && $bytes[1] == 0x32 && $bytes[2] == 0x33 ) { print "Match!\n"; } ```