Re: pack
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) -/-' /___/_<_http://www.todbe.com/ ___ Perl-Win32-Users mailing list [EMAIL PROTECTED] To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: pack
- 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 () { $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
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() { $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.) > > > > > > > while (1) { > > > > > sysread(READ, $ret, 4); > > > > > > 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 () { # 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] > 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
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 () { 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
RE: pack
> -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() 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 ... > 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 () { > 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
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() 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 ... 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 () { 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