Does the file change between loads? If not, you can just run through the file once and generate a list of line positions (use pack to compress each position into 4 bytes, rather than storing the positions as longer, not fixed-length strings), then from then on jump to the index position corresponding to the line you want, grab 4 bytes, unpack to find the line position, then go to that position in the main file and read the record.
Or you can use Tie::File, but where's the fun in that? :)