プロが教えるわが家の防犯対策術!

タイトル見ただけではなんのこっちゃかもわかりませんが
行いたい事は以下の通りです。

バイナリファイル(画像ファイル)、仮に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)
を格納したいのです。

この関数ではダメだと思うのですが、
自分の行いたい処理の関数が見当たらず困っております。

どなたかご存知の方、どうぞよろしくお願い致します。

A 回答 (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
 が使用できます。
    • good
    • 0
この回答へのお礼

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

お礼日時:2004/02/25 15:46

>15Kバイトの画像ファイルの10Kバイトの位置から


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

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

お礼日時:2004/02/25 15:45

sysread(BIN, $str2, 5000,10000);


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

この回答への補足

ご返答ありがとうございます。

試してみたのですが、自分の期待通りには動作しませんでした。
というのも、これは自分の説明不足だったので申し訳なかったです。

上記の形は説明の都合上同時に処理しているので
Read時のファイルポインター(?)の場所を覚えている為か
連続したsysreadでうまくいくのですが
ファイルを読み込ませたい処理は別々にしたいのです。

15Kバイトの画像ファイルの10Kバイトの位置から
$strに読み込みたいだけ、の時は
(ファイいるの先頭から10Kバイトの読み込みは処理しない)
やはりオフセットして読み込む必要があるのかな、と。

お手間を取らせて申し訳なかったですが、
再度ご教授頂けると助かります。

補足日時:2004/02/24 11:09
    • good
    • 0

シンプルに以下を試してみてください。



sysread(BIN, $str1, 10000);
sysread(BIN, $str2, 5000);

多分それでいけると思います。
つまり、オフセットの指定はいらないということです。

この回答への補足

ご返答ありがとうございます。

試してみたのですが、自分の期待通りには動作しませんでした。
というのも、これは自分の説明不足だったので申し訳なかったです。

上記の形は説明の都合上同時に処理しているので
Read時のファイルポインター(?)の場所を覚えている為か
連続したsysreadでうまくいくのですが
ファイルを読み込ませたい処理は別々にしたいのです。

15Kバイトの画像ファイルの10Kバイトの位置から
$strに読み込みたいだけ、の時は
(ファイいるの先頭から10Kバイトの読み込みは処理しない)
やはりオフセットして読み込む必要があるのかな、と。

お手間を取らせて申し訳なかったですが、
再度ご教授頂けると助かります。

補足日時:2004/02/24 11:09
    • good
    • 0

sysread()の第4引数は、文字列変数に対して作用します。

ですので、使い方を間違えているような。
素直に、
sysread BIN, $str1, 10000;
sysread BIN, $str2, 5000;
――で良いのでは。

この回答への補足

ご返答ありがとうございます。

試してみたのですが、自分の期待通りには動作しませんでした。
というのも、これは自分の説明不足だったので申し訳なかったです。

上記の形は説明の都合上同時に処理しているので
Read時のファイルポインター(?)の場所を覚えている為か
連続したsysreadでうまくいくのですが
ファイルを読み込ませたい処理は別々にしたいのです。

15Kバイトの画像ファイルの10Kバイトの位置から
$strに読み込みたいだけ、の時は
(ファイいるの先頭から10Kバイトの読み込みは処理しない)
やはりオフセットして読み込む必要があるのかな、と。

お手間を取らせて申し訳なかったですが、
再度ご教授頂けると助かります。

補足日時:2004/02/24 11:08
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!