gary kuipers has asked for the wisdom of the Perl Monks concerning the following question:

I need to read a file at a starting position ( != 0) and keep reading until I encounter a "\n" (ordinal 10), then stop. I am using sysopen, sysseek and sysread. The characters I am fetching are just fine (they display properly). The problem comes in when I try to determine the ordinal value of the just-read character ($c):

sysread(RCVQ,$c,1,$ptr);

my $x = ord($c); print "$c=$x\n"; yields T=0 (zero). Actually all characters are = ordinal 0, which is clearly wrong.

ord() will provide the correct ordinal number if I say ord('E') or $c = 'E'; ord($c). So it is not ord() that is broken.

per dox, ord() returns the ordinal value of the first character of the string it is passed. Does Perl infer that $c is a character and pass a 2 or more byte string (unicode??) to ord() ???
  • Comment on string and sysread and read work differently

Replies are listed 'Best First'.
Re: string and sysread and read work differently
by seattlejohn (Deacon) on Dec 24, 2002 at 00:29 UTC
    Is $ptr zero when you call sysread? What happens if you omit $ptr from the call?

    If $ptr is nonzero, sysread is going to insert the characters into $c someplace other than the beginning of the string. I would suspect that $c gets filled from the left with chr(0) if needed, which is why ord then returns 0.

    If you wanted to reliably get the ordinal of the string you just read, I think you'd need to use something like my $x = ord(substr($c,$ptr,1));. Or get rid of $ptr (or make sure it's really 0) so you are actually reading into the beginning of $c.

            $perlmonks{seattlejohn} = 'John Clyman';

      DOH!

      I am using the OFFSET $ptr as an offset in the file I am reading instead of what it really is ... an offset into the string I am placing the data into.

      ARRRGH! Too tired!

      Thanks for your help!!!
Re: string and sysread and read work differently
by Zaxo (Archbishop) on Dec 24, 2002 at 00:36 UTC

    It would be simpler to use the buffered operations for this. That gives you automatic record seperator detection:

    my $string { local $/ = "\n"; open my $fle, '<', $filepath or die $!; seek $fle, $offset, 0 or die $!; $string = <$fle>; close $fle or die $!; }
    You could position without seek by first reading a dummy line with local $/ = \$offset;, but that is unnecessarily opaque.

    After Compline,
    Zaxo