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(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
- 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
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
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
-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
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