- ベストアンサー
バイナリファイル(画像等)データをオフセットして読み込みたい
タイトル見ただけではなんのこっちゃかもわかりませんが 行いたい事は以下の通りです。 バイナリファイル(画像ファイル)、仮に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) を格納したいのです。 この関数ではダメだと思うのですが、 自分の行いたい処理の関数が見当たらず困っております。 どなたかご存知の方、どうぞよろしくお願い致します。
- みんなの回答 (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 が使用できます。
その他の回答 (4)
- tatsu99
- ベストアンサー率52% (391/751)
>15Kバイトの画像ファイルの10Kバイトの位置から >$strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) >やはりオフセットして読み込む必要があるのかな、と。 seek命令を実行後、読み込んで下さい。 seek(BIN,10000,0); sysread(BIN, $str2, 5000); でファイルの10000バイト以降から5000バイトを 読み込めます。(動作確認してないので自信なし)
お礼
ありがとうございます。 解決しました。
- tatsu99
- ベストアンサー率52% (391/751)
sysread(BIN, $str2, 5000,10000); は誤りです。 sysread(BIN, $str2, 5000); としてください。 これであなたが望んだ結果が得られます。 10000の意味は、$str2の10000バイト目以降へ読み込んだデータをセットするという意味です。ファイルの10000バイト目からデータを読み込むという意味ではありません。
補足
ご返答ありがとうございます。 試してみたのですが、自分の期待通りには動作しませんでした。 というのも、これは自分の説明不足だったので申し訳なかったです。 上記の形は説明の都合上同時に処理しているので Read時のファイルポインター(?)の場所を覚えている為か 連続したsysreadでうまくいくのですが ファイルを読み込ませたい処理は別々にしたいのです。 15Kバイトの画像ファイルの10Kバイトの位置から $strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) やはりオフセットして読み込む必要があるのかな、と。 お手間を取らせて申し訳なかったですが、 再度ご教授頂けると助かります。
- natsuki_tk
- ベストアンサー率35% (99/279)
シンプルに以下を試してみてください。 sysread(BIN, $str1, 10000); sysread(BIN, $str2, 5000); 多分それでいけると思います。 つまり、オフセットの指定はいらないということです。
補足
ご返答ありがとうございます。 試してみたのですが、自分の期待通りには動作しませんでした。 というのも、これは自分の説明不足だったので申し訳なかったです。 上記の形は説明の都合上同時に処理しているので Read時のファイルポインター(?)の場所を覚えている為か 連続したsysreadでうまくいくのですが ファイルを読み込ませたい処理は別々にしたいのです。 15Kバイトの画像ファイルの10Kバイトの位置から $strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) やはりオフセットして読み込む必要があるのかな、と。 お手間を取らせて申し訳なかったですが、 再度ご教授頂けると助かります。
- osamuy
- ベストアンサー率42% (1231/2878)
sysread()の第4引数は、文字列変数に対して作用します。ですので、使い方を間違えているような。 素直に、 sysread BIN, $str1, 10000; sysread BIN, $str2, 5000; ――で良いのでは。
補足
ご返答ありがとうございます。 試してみたのですが、自分の期待通りには動作しませんでした。 というのも、これは自分の説明不足だったので申し訳なかったです。 上記の形は説明の都合上同時に処理しているので Read時のファイルポインター(?)の場所を覚えている為か 連続したsysreadでうまくいくのですが ファイルを読み込ませたい処理は別々にしたいのです。 15Kバイトの画像ファイルの10Kバイトの位置から $strに読み込みたいだけ、の時は (ファイいるの先頭から10Kバイトの読み込みは処理しない) やはりオフセットして読み込む必要があるのかな、と。 お手間を取らせて申し訳なかったですが、 再度ご教授頂けると助かります。
お礼
丁寧な解説ありがとうございました。 おかげで解決しました。