Re: pack

2002-02-21 Thread Will W


Hi, Carl--

Using the input record separator for fixed length records does work,
just as the the fine manual says. However I left out one critical
character in the code I sent last night-- the magic happens when $/ is
assigned a _reference_ to an integer value, as below.

use strict;
{
local $/;
   $/ = \4; # must be reference
   open IN, test.dbx or die bad open: $!\n;
   binmode IN;
   my $i = 0;
   my $n = 0;
   while(IN) {
  $n = unpack(I, $_);
  printf %02d. %08X\n, $., $n;
  $i++;
  last if $i  10;
   }
   close IN;
}

This behavior is documented in Wall, et al: _Programming perl, third
ed_, pg 666 (so I guess its sort of black magic). The above bit also
shows that $. does work in this mode.

--Will



Carl Jolley wrote on Thursday, February 21, 2002 1:35 PM
Subject: Re: pack


 On Thu, 21 Feb 2002, Will W wrote:

  Sisyphus wrote on Wednesday, February 20, 2002 5:16 PM
  Subject: Re: pack
 
 
   Thanks Will . now for a replacement for '$.' ?? :-))
   (Of course it's dead easy to craft one's own incremental counter.)
  snip
 while (1) {
 sysread(READ, $ret, 4);
  snip
 
  Everyone's fascination with sysread() got me to poking around in the
  camel and cookbook a bit-- and I still can't see the advantage here
of
  doing a low-level system call over using read(), which is generally
  buffered for optimal efficiency on whatever system your using.
sysread()
  makes a lot of sense on a port, but on a disk file I'm not seeing
the
  why of it-- maybe someone will enlighten me.
 
  Anyway while poking around I ran yet another way to do the job which
  really looks kind of interesting:
 
  [untested-- too much chianti on board to try it tonight]
 
  open IN, $somefile or die gasp! $somefile! Uh! $!\n;
  binmode IN;
  { # closure for local
  local $/;
  $/ = 4; # see the camel
  while (IN) { # Should work, but wait there's more
  $n = unpack(I, $_); # may have mangled the syntax
  $line = $.;# Yep, you get this too!
  } # endwhile
  } # end localizing closure
 
  Now its time for bed. Spent the day developing a single subroutine
I'm
  calling recurse_the_kids because its so dang descriptive of my
feelings
  about its convolutions. And I'm out of chianti anyway.
 

 By doing a: $/ = 4; all you've done is to set the input record
seperator
 character to a character 4. That will mean that if your file
contained
 the characters 0123456789 that doing a  on that file would result
 in two records being read. The first one would contain 01234 and the
 second (and last) one would contain 56789. By default, $/ is the
 new-line character. Changing it tells perl that a different character
 should be used to separate records. If you set $/ to undefined, then
 the first  operation on the filehandle will read all the characters
 it contains. Setting $/ has no effect if you are using read() or
 sysread() to access the data since those function read a specified
 number of characters not a record.


  [EMAIL PROTECTED] Carl Jolley
  All opinions are my own and not necessarily those of my employer

 k


___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



Re: pack

2002-02-21 Thread Sisyphus


- Original Message -
From: Will W [EMAIL PROTECTED]


 Everyone's fascination with sysread() got me to poking around in the
 camel and cookbook a bit-- and I still can't see the advantage here of
 doing a low-level system call over using read(), which is generally
 buffered for optimal efficiency on whatever system your using. sysread()
 makes a lot of sense on a port, but on a disk file I'm not seeing the
 why of it-- maybe someone will enlighten me.


To have a closer look at 'read' versus 'sysread' I did a benchmark test.

I found that 'sysread' took (almost exactly) twice as long as 'read'.

So that was a pretty pertinent point you raised, Will.
Guess I'd have to agree that I, too, don't see the advantage of using
sysread in preference to read.

I also ran the same code using the trick with '$/' (which is also mentioned
in perlvar, btw). Not surprisingly it's pretty much the same speed as
'read'.

Here's a cut'n'paste of both the code I ran and the result I got. Sorry if
it gets wrapped inconveniently.

use Benchmark;

timethese (1, {

'sysread' = 'open (READ, d:/pscrpt/tab.new)
 or die Cannot open READ: $!;
binmode READ;

while (sysread(READ, $read, 4) == 4) {
 $mod = unpack(I, $read);
 }

print $mod\n;

close (READ) or die Cannot close READ: $!;',


'read' = 'open (READ, d:/pscrpt/tab.new)
 or die Cannot open READ: $!;
binmode READ;

while (read(READ, $read, 4) == 4) {
 $mod = unpack(I, $read);
 }
print $mod\n;

close (READ) or die Cannot close READ: $!;',

'local' = '{
 local $/;
 $/ = \4;
open (READ, d:/pscrpt/tab.new)
 or die Cannot open READ: $!;
binmode READ;

while (READ) {
 $mod = unpack(I, $_);
 }
print $mod\n;

close (READ) or die Cannot close READ: $!;
}',
});

##

Benchmark: timing 1 iterations of local, read, sysread...
27112421
 local: 25 wallclock secs (24.90 usr +  0.09 sys = 24.98 CPU) @  0.04/s
 (n=1)
(warning: too few iterations for a reliable count)
27112421
  read: 26 wallclock secs (26.42 usr +  0.10 sys = 26.52 CPU) @  0.04/s
 (n=1)
(warning: too few iterations for a reliable count)
27112421
   sysread: 53 wallclock secs (34.20 usr + 17.39 sys = 51.59 CPU) @  0.02/s
 (n=1)
(warning: too few iterations for a reliable count)

Cheers,
Rob

___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



Re: pack

2002-02-21 Thread $Bill Luebkert

Sisyphus wrote:

 - Original Message -
 From: Will W [EMAIL PROTECTED]
 
Everyone's fascination with sysread() got me to poking around in the
camel and cookbook a bit-- and I still can't see the advantage here of
doing a low-level system call over using read(), which is generally
buffered for optimal efficiency on whatever system your using. sysread()
makes a lot of sense on a port, but on a disk file I'm not seeing the
why of it-- maybe someone will enlighten me.


 
 To have a closer look at 'read' versus 'sysread' I did a benchmark test.
 
 I found that 'sysread' took (almost exactly) twice as long as 'read'.
 
 So that was a pretty pertinent point you raised, Will.
 Guess I'd have to agree that I, too, don't see the advantage of using
 sysread in preference to read.
 
 I also ran the same code using the trick with '$/' (which is also mentioned
 in perlvar, btw). Not surprisingly it's pretty much the same speed as
 'read'.


sysread is unbuffered.  To get the same kind of results, you would need
to read a block of data and then feed the data 4 bytes at a time from a
subroutine that holds the buffered data and do another read when you run
out of data in that block.

-- 
   ,-/-  __  _  _ $Bill Luebkert   ICQ=14439852
  (_/   /  )// //   DBE Collectibles   Mailto:[EMAIL PROTECTED]
   / ) /--  o // //  http://dbecoll.tripod.com/ (Free site for Perl)
-/-' /___/__/_/_ Castle of Medieval Myth  Magic http://www.todbe.com/

___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



RE: pack

2002-02-20 Thread Morse, Richard E.

Hah!  I know what the problem is!

ASCII character 10 happens to be either \n -- so when you print this number to
the file, you get a newline character for one of the bytes, so your
while(READ) loop finds three lines in the file instead of two.

I think that in order to read this number back out of the file, you'll have to
use sysread, instead of READ...

HTH,
Ricky

-Original Message-
From: Sisyphus [mailto:[EMAIL PROTECTED]]
Sent: Wednesday 20 February 2002 9:11 AM
To: [EMAIL PROTECTED]
Subject: pack 


Hi,

Ok - so I'm running the code below and it's working as I want - unless
either of the 2 values being written to the file is 10. (ie unless $num = 8
or 10).

If the value is 10, then I get a couple of warnings about 'use of
uninitialised value'.
'10' is the only value I've found that exhibits this disgraceful behaviour.

U .. I'm a little hard pressed to make sense of that 
something to do with the newline characters or the chomping perhaps ?

use warnings;
my $file = try;
my $num = 2;
open (WRITEB, $file)
or die Can't open WRITEB: $!;
binmode WRITEB;
print WRITEB pack(I,$num,), \n;
print WRITEB pack(I,$num + 2), \n;
close (WRITEB)
 or die Can't close WRITEB: $!;

open (READ, $file)
or die Can't open READ: $!;
binmode READ;
while (READ) {
chomp;
$ret = unpack(I, $_);
print $ret, \n;
}
close (READ)
 or die Can't close READ: $!;

Cheers,
Rob


___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



RE: pack

2002-02-20 Thread Joe Schell



 -Original Message-
 Behalf Of Morse, Richard E.

 Hah!  I know what the problem is!

 ASCII character 10 happens to be either \n -- so when you print
 this number to
 the file, you get a newline character for one of the bytes, so your
 while(READ) loop finds three lines in the file instead of two.

 I think that in order to read this number back out of the file,
 you'll have to
 use sysread, instead of READ...


In addition to the above you might want to look at why you would want a '\n'
in the file at all.  That is useful in a human readable file, but the file
you will end up with will not be readable.  And if you are looking for an
end of data marker I don't think a single character (or two for win32) is
going to be sufficient.  Either 0x or 0x are probably better choices
(or the 4 byte versions of each.)


 -Original Message-
 From: Sisyphus [mailto:[EMAIL PROTECTED]]

 Hi,

 Ok - so I'm running the code below and it's working as I want - unless
 either of the 2 values being written to the file is 10. (ie
 unless $num = 8
 or 10).

 If the value is 10, then I get a couple of warnings about 'use of
 uninitialised value'.
 '10' is the only value I've found that exhibits this disgraceful
 behaviour.

 U .. I'm a little hard pressed to make sense of that 
 something to do with the newline characters or the chomping perhaps ?

 use warnings;
 my $file = try;
 my $num = 2;
 open (WRITEB, $file)
 or die Can't open WRITEB: $!;
 binmode WRITEB;
 print WRITEB pack(I,$num,), \n;
 print WRITEB pack(I,$num + 2), \n;
 close (WRITEB)
  or die Can't close WRITEB: $!;

 open (READ, $file)
 or die Can't open READ: $!;
 binmode READ;
 while (READ) {
 chomp;
 $ret = unpack(I, $_);
 print $ret, \n;
 }
 close (READ)
  or die Can't close READ: $!;


___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs



Re: pack

2002-02-20 Thread Torsten Förtsch

On Thu, 21 Feb 2002 01:11:01 +1100
Sisyphus [EMAIL PROTECTED] wrote:

 Hi,
 
 Ok - so I'm running the code below and it's working as I want - unless
 either of the 2 values being written to the file is 10. (ie unless $num = 8
 or 10).
 
 If the value is 10, then I get a couple of warnings about 'use of
 uninitialised value'.
 '10' is the only value I've found that exhibits this disgraceful behaviour.
 
 U .. I'm a little hard pressed to make sense of that 
 something to do with the newline characters or the chomping perhaps ?
 
 use warnings;
 my $file = try;
 my $num = 2;
 open (WRITEB, $file)
 or die Can't open WRITEB: $!;
 binmode WRITEB;
 print WRITEB pack(I,$num,), \n;

if $num==10 you are really printing \n\0\0\0\n to the file on a little
endian machine like a PC. pack( I, 10 ) gives \n\0\0\0. The least
significant byte is 10 which is the ASCII newline character.

 print WRITEB pack(I,$num + 2), \n;
 close (WRITEB)
  or die Can't close WRITEB: $!;
 
 open (READ, $file)
 or die Can't open READ: $!;
 binmode READ;
 while (READ) {

Here you want to read one line at a time. If $num was 10 you will get 2
lines. The first one will be \n the 2nd \0\0\0\n.

 chomp;

chomp makes  from \n.

 $ret = unpack(I, $_);

unpack( I,  ) yields undef.

 print $ret, \n;

and here you get your warning

 }
 close (READ)
  or die Can't close READ: $!;
 

In generally do not mix binary and line oriented IO. In your example you
can 
  print WRITEB pack(I,$num,);
without the newline and then use read or sysread:
  read READ, $_, length( pack( I, 0 ) );

 Cheers,
 Rob
 
 
 ___
 Perl-Win32-Users mailing list
 [EMAIL PROTECTED]
 To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
 
___
Perl-Win32-Users mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs