Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!umich!yale!think!zaphod.mps.ohio-state.edu!brutus.cs.uiuc.edu!jarthur!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: Write(2) in Perl Message-ID: <6831@jpl-devvax.JPL.NASA.GOV> Date: 19 Jan 90 01:20:15 GMT References: <1585@cipc1.Dayton.NCR.COM> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Distribution: usa Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 62 In article <1585@cipc1.Dayton.NCR.COM> tbertels@cipc1.Dayton.NCR.COM (Tom Bertelson) writes: : While working on a Perl program that will move a lot of binary data I : discovered the following in the manual: : : Note that write is NOT the opposite of read. : : I can use read and unpack to handle the data coming in, but how can I : get it out again? I'm currently using 'printf STDOUT "%128s", : $buffer;', but want to use a larger buffer (it writes to a streaming : tape). Am I missing something obvious, ar am I just out of luck? The reason I haven't added a write of the system call variety is that it seems that print can already do the same thing. I needed a read because normal input is line oriented, but the normal print just puts out how ever many characters there are. If your string happens to be 64k long, then it fwrite()s 64k in one fell swoop. Hopefully fwrite() is written smart enough to not copy data it doesn't need to before calling the system call write(). (Note that a perl read() in fact calls fread() rather than system call read(). We have to make sure that stdio stays notified of our current FILE status.) As for how to make sure your string is 64k (or whatever) long, there are of course several ways to do it. You can do padding with either pack() or "\0" x (64 * 1024 - length($foo)); However, it's probably better to use the fact that substr() can be used as an lvalue. Say $buf = "\0" x (64 * 1024); (or, much more efficiently, till I optimize the foregoing) $buf = "\0" x 1024 x 64; and then, to set the first n bytes of it: substr($buf,0,length($foo)) = $foo; If you assign to a substr a string that is the same length as that specified in the 3rd argument, the string is modified in place. (If it's shorter, some of the target string may get copied. If it's longer, the entire targer string may be copied.) Things get a little more complicated if the length of $foo may run it off the end of $buf, but you can figure out how to check for that. Good luck. I don't know that I'd be brave enough to try to make a tape stream in perl, but you're welcome to try. If your fread() and fwrite() are implemented to bypass stdio buffers when they can, then you might actually be able to do it. If not, you could have problems unless your CPU really screams. One of these days when I haven't anything better to do, I may make perl output cheat on stdio when it can get away with it, but till then you're at the mercy of your fwrite() implementation. Just checked--the 4.2 fwrite() stinks--does an extra memory reference on each byte it copies to the stdout buffer. The 4.3 fwrite() at least calls bcopy, but it doesn't appear to call write directly when it can (guessing from the symbol table here) unless it fiddles the buffer pointer temporarily and lets flsbuf do the write. SunOS 4.0.3 appears to call write directly (again guessing from the symbol table). Sigh. Wish I had more source access, if just for reference... So, it looks like it depends on your fwrite(). Like the manual says, perl can do binary, but most of the polish has gone into text processing. Larry