IzziD code logo

Topics

Home

Bioinfo

Web

Misc

About

Other IzziDs

IzziDassorted

IzziDtravel

IzziDwetlab

IzziD

How to move back a line when reading a Perl filehandle

Article created: Jan 21, 2008
Article by: Jeremiah Faith

The angle operator <> is the standard method to read lines from a file with Perl:

my $file="myfile.txt";
open(IN, $file) or die "can't open $file: $!\n";

while (<IN>) {   # place each line into $_
	print;   # print $_
}

The angle operator reads a single line from the file and places it into the variable you provide or into $_ if you do not provide a variable. If you use the angle operator outside of a loop, you will read a single line only.

my $file="myfile.txt";

open(IN, $file) or die "can't open $file: $!\n";

my $line = <IN>;   # place a single line into $line
print $line;

Last week, I was writing a recursive function in Perl where I needed to read a line from the Perl filehandle. If it was the correct type of line for my recursive depth, I would process the line, otherwise I wanted to put the line back on the filehandle, so that the remaining recursive depths would have access to the line.

I dug around the Perl Camel Book and the internet, and I couldn’t find a function that would allow me to unread a line. I found a few modules that would allow such a thing, but a module seemed like overkill for such a simple task. So I wrote the code myself:

my $file="myfile.txt";
open(IN, $file) or die "can't open $file: $!\n";

my $line = <IN>;   # place a single line into $line
seek(IN, -length($line), 1); # place the same line back onto the filehandle

To move back a line, I use the built-in seek() function. Which takes the parameters: FILEHANDLE, OFFSET, and WHENCE. WHENCE can take a value of 0, 1, or 2. 0 = seek from the start of the file; 1 = seek from the current position; 2 = seek from the end of the file. OFFSET is the number of bytes we wish to move from the specified WHENCE position. OFFSET can be negative with a WHENCE of 1 or 2 (a negative OFFSET moves back in the file). Since each letter in an ASCII string is one byte, we simply move back from our current file position (i.e. WHENCE = 1) the number of bytes we read for the previous $line (i.e. -length($line)).

Caveats

For this function to work properly, you must call the length() function on the original string that’s been read from the filehandle. If you call chomp on the line, you’ve likely changed the length of the string and you won’t seek back far enough. This function also assumes your string contains eight bit characters.