• ベストアンサー

バイナリファイル(画像等)データをオフセットして読み込みたい

タイトル見ただけではなんのこっちゃかもわかりませんが 行いたい事は以下の通りです。 バイナリファイル(画像ファイル)、仮に15Kバイトのサイズだったとします。 それを10Kバイト区切りで読み込みたい。 そして変数$str1,$str2に格納したい。 open(BIN, "< test.gif"); binmode(BIN); #ファイルの先頭から10Kバイト読み込んで変数$str1に代入 sysread(BIN, $str1, 10000); #上記で読み込んだ個所から、残りのデータを読み込みたい #オフセット10Kバイトから5Kバイト読み込む sysread(BIN, $str2, 5000,10000); close(BIN); のような処理でいいのかと思っていたのですが、 $str2には期待通りの形で格納されませんでした。 先頭の10000バイト(オフセットで指定したサイズ)がNULLになっており、 その先から残りのバイナリデータが格納されていました。 自分が行いたいのは、 $str2の先頭から、バイナリファイルのオフセットの値 (ここでは10Kの部分からのこりの5K) を格納したいのです。 この関数ではダメだと思うのですが、 自分の行いたい処理の関数が見当たらず困っております。 どなたかご存知の方、どうぞよろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.5

ファイル読み書きの位置を指定する場合は、seek を使いファイルポインタをセットします。 書式:  seek ファイルハンドル, オフセット, 起点  起点には次の値を指定します。   0: ファイルの先頭   1: 現在位置   2: ファイルの末尾  戻値は新しいポジション(ファイル先頭からのオフセット)で、失敗時には未定義値(undef)が返ります。 # 先頭から10000バイト目にファイルポインタをセット  seek BIN, 10000, 0; ただし、sysread などを使っている場合、seek ではバッファリングの影響が出ることがあるので、sysseek を使った方がよいでしょう。使い方は seek と同じです。 また起点には、IO::Seekable か POSIX モジュールから定数をインポートして使用することができます。   use IO::Seekable;  または   use POSIX;  をしておくと、   SEEK_SET  0   SEEK_CUR  1   SEEK_END  2  が使用できます。

hiro-long
質問者

お礼

丁寧な解説ありがとうございました。 おかげで解決しました。

その他の回答 (4)

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

>15Kバイトの画像ファイルの10Kバイトの位置から >$strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) >やはりオフセットして読み込む必要があるのかな、と。 seek命令を実行後、読み込んで下さい。 seek(BIN,10000,0); sysread(BIN, $str2, 5000); でファイルの10000バイト以降から5000バイトを 読み込めます。(動作確認してないので自信なし)

hiro-long
質問者

お礼

ありがとうございます。 解決しました。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

sysread(BIN, $str2, 5000,10000); は誤りです。 sysread(BIN, $str2, 5000); としてください。 これであなたが望んだ結果が得られます。 10000の意味は、$str2の10000バイト目以降へ読み込んだデータをセットするという意味です。ファイルの10000バイト目からデータを読み込むという意味ではありません。

hiro-long
質問者

補足

ご返答ありがとうございます。 試してみたのですが、自分の期待通りには動作しませんでした。 というのも、これは自分の説明不足だったので申し訳なかったです。 上記の形は説明の都合上同時に処理しているので Read時のファイルポインター(?)の場所を覚えている為か 連続したsysreadでうまくいくのですが ファイルを読み込ませたい処理は別々にしたいのです。 15Kバイトの画像ファイルの10Kバイトの位置から $strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) やはりオフセットして読み込む必要があるのかな、と。 お手間を取らせて申し訳なかったですが、 再度ご教授頂けると助かります。

回答No.2

シンプルに以下を試してみてください。 sysread(BIN, $str1, 10000); sysread(BIN, $str2, 5000); 多分それでいけると思います。 つまり、オフセットの指定はいらないということです。

hiro-long
質問者

補足

ご返答ありがとうございます。 試してみたのですが、自分の期待通りには動作しませんでした。 というのも、これは自分の説明不足だったので申し訳なかったです。 上記の形は説明の都合上同時に処理しているので Read時のファイルポインター(?)の場所を覚えている為か 連続したsysreadでうまくいくのですが ファイルを読み込ませたい処理は別々にしたいのです。 15Kバイトの画像ファイルの10Kバイトの位置から $strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) やはりオフセットして読み込む必要があるのかな、と。 お手間を取らせて申し訳なかったですが、 再度ご教授頂けると助かります。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

sysread()の第4引数は、文字列変数に対して作用します。ですので、使い方を間違えているような。 素直に、 sysread BIN, $str1, 10000; sysread BIN, $str2, 5000; ――で良いのでは。

hiro-long
質問者

補足

ご返答ありがとうございます。 試してみたのですが、自分の期待通りには動作しませんでした。 というのも、これは自分の説明不足だったので申し訳なかったです。 上記の形は説明の都合上同時に処理しているので Read時のファイルポインター(?)の場所を覚えている為か 連続したsysreadでうまくいくのですが ファイルを読み込ませたい処理は別々にしたいのです。 15Kバイトの画像ファイルの10Kバイトの位置から $strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) やはりオフセットして読み込む必要があるのかな、と。 お手間を取らせて申し訳なかったですが、 再度ご教授頂けると助かります。

関連するQ&A