In Perl, why can't you use __DATA__ as a seekable filehandle?
In Perl, why can't you use __DATA__ as a seekable filehandle?
Reading from DATA via the typical slurp works. Trying to use DATA as a filehandle on which I can do a seek does not work. Is anyone able to point me the to the obvious mistake I must be making?
Code:
#!/usr/bin/env perl
use strict;
use warnings;
if ($ARGV[0] eq 'seek' )
my $log_fh = *DATA;
$log_fh->seek(64,0);
print "n-- 64 --n",join ("", <$log_fh> );
else
while (<DATA>)
print $_;
exit;
__DATA__
01234567890123456789
1234567890123456789
1234567890123456789
12
X <- That X is the 64th char in
this file.
Y <- That Y is the 106th char in this file.
junk
more junk.
bye!
$ perl file_from_data.pl slurp
01234567890123456789
1234567890123456789
1234567890123456789
12
X <- That X is the 64th char in
this file.
Y <- That Y is the 106th char in this file.
junk
more junk.
bye!
Running the while() loop:
$ perl file_from_data.pl slurp
01234567890123456789
1234567890123456789
1234567890123456789
12
X <- That X is the 64th char in
this file.
Y <- That Y is the 106th char in this file.
junk
more junk.
bye!
Running the seek(), it appears to not start at DATA but the start of the script:
$ perl file_from_data.pl seek
-- 64 --
'seek' )
my $log_fh = *DATA;
$log_fh->seek(64,0);
print "n-- 64 --n",join ("", <$log_fh> );
else
while (<DATA>)
print $_;
exit;
__DATA__
01234567890123456789
1234567890123456789
1234567890123456789
12
X <- That X is the 64th char in
this file.
Y <- That Y is the 106th char in this file.
junk
more junk.
bye!
This is an old Perl:
$ perl -v
This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-
thread-multi
DATA
tell(DATA)
DATA
Avoid DATA if you need it seekable; use a separate file instead. Is this for a module you are distributing?
– ysth
Aug 30 at 20:43
For what it's worth, take a look at metacpan.org/pod/Data::Section::Simple. Not exactly what you describe you want to do, but maybe useful anyway.
– simbabque
Aug 31 at 8:50
@simbabque - I will keep this in my League of Extraordinary CPAN Modules. :-) Thank you.
– mpersico
Sep 1 at 13:36
1 Answer
1
Running the seek(), it appears to not start at DATA but the start of the script
I don't think you're making any mistake at all. That's exactly what happens. DATA
is a filehandle that is open on your source file. Before your first read()
from that filehandle, the file pointer is positioned immediately after the __DATA__
token in the file. But you can use seek()
to move the file pointer to any position at all in the file.
DATA
read()
__DATA__
seek()
I guess it would be harder to implement a "special case" filehandle that wasn't able to move back before its initial position.
OP can just use SEEK_CUR (instead of SEEK_SET) as the whence.
– mwp
Aug 30 at 20:10
Duh - special semantics. So I should while() until DATA, get that position, then all seeks are relative to that. Sounds like something that is either on CPAN or should be. Thank you.
– mpersico
Aug 30 at 20:11
@mwp - Thanks! That worked: $log_fh->seek(64,1);
– mpersico
Aug 30 at 20:13
The other thing to do is:
my $log_fh = *main::DATA; my $whence = $log_fh->tell(); $log_fh->seek($whence + 64,0); print "n-- 64 --n",join ("", <$log_fh> );
– mpersico
Aug 30 at 20:18
my $log_fh = *main::DATA; my $whence = $log_fh->tell(); $log_fh->seek($whence + 64,0); print "n-- 64 --n",join ("", <$log_fh> );
@mpersico, Don't search for
__DATA__
. You're already positioned there. Use SEEK_CUR
to move forwards 64 bytes. If you need to seek back to the start, use tell
to note the start position (before doing any seeking or reading)– ikegami
Aug 30 at 20:53
__DATA__
SEEK_CUR
tell
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
DATA
is seekable. Store the result oftell(DATA)
when the script starts and treat that as the first byte of theDATA
stream.– mob
Aug 30 at 20:25