ファイルの読み込み開始位置と終了位置を指定して書き出す〜seek、read

●ポイント

◎seek([ファルハンドル], [起点からの位置(スタート地点になる)], [起点]);
起点は、0だとファイルの先頭、1だと現在の位置、2だとファイルの末尾になる。(0, 1, 2以外は入りません)
例),
seek($fh, 20,0);
→ファイルの先頭から20バイト進んだところが読み込み・書き込み位置になる。

◎read([ファイルハンドル], [読み込んだ情報を格納するスカラー変数], [読み込む情報の終点])

●お題
こんな↓ファイル(test_yoko_ryouri.eps)があるとします。

プレビュー情報を読み取って、TIFFファイルのみを抽出して保存してください。

#! /usr/bin/perl

use strict;
use warnings;

#何度もこのスクリプトを回して大丈夫なように、既に抽出したTIFFファイルがあるときは消去しておく
system("rm copy_ryouri.tif") if -e "copy_ryouri.tif";

#epsファイルを読み取りモードで、書き出すTIFFファイルをcopy_ryouri.tifという名前でopenする
open(my $fh,'<','test_yoko_ryouri.eps') || die "can't open (test_yoko_ryouri.eps)";
open(my $out,'>','copy_ryouri.tif') || die "can't open (copy_ryouri.tif)";

#プレビュー情報(ファイルの先頭から30バイト)を読み込む
read ($fh, my $offset_info, 30);    # my $offset_info = <$fh>; だと、一行読み込める。

#プレビュー情報から、TIFFファイルの開始位置とサイズを取得
my $start_point = substr($offset_info,20,4);
my $size = substr($offset_info,24,4);

#読み取った開始位置とサイズは、バイナリ情報のため変換する(バイナリファイルでなければしなくてよい)
$start_point = unpack("v", $start_point);
$size = unpack("v", $size);

#ファイルの読み込み開始位置を指定
seek($fh, $start_point, 0);

#指定した読み込み開始位置からTIFFファイルのサイズまでファイルを読み込む(TIFFファイルの抽出)
read($fh, my $data, $size);

#抽出したTIFFファイルの書き出し
print $out $data;

#ファイルをクローズ
close($out);
close($fh);

以下、参考になったサイトです。


■unpack
http://perl.misty.ne.jp/function02/unpack.html
■unpackで指定できる型指定文字列
http://perl.misty.ne.jp/function01/pack_option.html


短く書けないか、がんばってみた。もっと短く書く方法があったら教えてください。

#! /usr/bin/perl

use strict;
use warnings;

system("rm copy_ryouri.tif") if -e "copy_ryouri.tif";

open(my $fh,'<','test_yoko_ryouri.eps') || die "can't open (test_yoko_ryouri.eps)";
open(my $out,'>','copy_ryouri.tif') || die "can't open (copy_ryouri.tif)";

my $offset_info = <$fh>;

seek($fh, (unpack "v", (substr($offset_info, 20, 4))),0);
read($fh, my $data, (unpack "v", (substr($offset_info,24,4))));
print $out $data;
close($out);
close($fh);