Perl seek function

sflee picture sflee · May 15, 2013 · Viewed 17.5k times · Source

This problem was solved. Thank you very much.
My question and the solution I am using is stated below.

Question:

open IN, "<./test.txt";
seek(IN,10,0);
read IN, $temp, 5;

seek(IN,20,0);
close(IN);


The situation is that, my handle will start at position 0.
After the first seek function, my file handle will at position 10.
After I read, my handle will at position 15.
At this moment, I seek again. Then the program will seek from the beginning or from position 20.
My question is that is there anyway for me to do searching in a file so that I do not need to search from the starting point of the file every time?


The way I am using:

use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END); #SEEK_SET=0 SEEK_CUR=1 ...

$target_byte=30;
open IN, "<./test.txt";
seek(IN,10,SEEK_SET);
read IN, $temp, 5;

$position=tell(IN);
seek(IN,$target_byte-$position,SEEK_CUR);
#do what I want
close(IN);

Answer

ikegami picture ikegami · May 15, 2013

Before we start,

  • The assumption you ask us to make no sense. The first byte is at position zero. Always.

  • It's called a "file handle" (since it allows you to hold onto a file), not a "file handler" (since it doesn't handle anything).

It would be clearer if you used the constants SEEK_SET, SEEK_CUR and SEEK_END instead of 0, 1 and 2.

Your code is then

use Fcntl qw( SEEK_SET );

open IN, "<./test.txt";
seek(IN,10,SEEK_SET);
read IN, $temp, 5;

seek(IN,20,SEEK_SET);
close(IN);

As the name implies, it sets the position to the specified value.

So,

  • After the first seek, the file position will be 10.
  • After the read, the file position will be 15.
  • After the second seek, the file position will be 20.

Visually,

         +--------------------------  0: Initially.
         |         +---------------- 10: After seek($fh, 10, SEEK_SET).
         |         |    +----------- 15: After reading "KLMNO".
         |         |    |    +------ 20: After seek($fh, 20, SEEK_SET).
         |         |    |    |
         v         v    v    v     
file:    ABCDEFGHIJKLMNOPQRSTUVWXYZ
indexes: 01234567890123456789012345

If you wanted to seek relative to your current position, you'd use SEEK_CUR.

         +--------------------------  0: Initially.
         |         +---------------- 10: After seek($fh, 10, SEEK_CUR).
         |         |    +----------- 15: After reading "KLMNO".
         |         |    |         +- 25: After seek($fh, 10, SEEK_CUR).
         |         |    |         |
         v         v    v         v 
file:    ABCDEFGHIJKLMNOPQRSTUVWXYZ
indexes: 01234567890123456789012345