C0361%UNIVSCVM.BITNET@ncsuvm.ncsu.edu ( Thomas Jenkins) (06/06/90)
Hello, Well, I've run into an error. I've written two programs in TP 5.5. One, FSPLIT, will accept two commandline arguments: a filename and a legal number. These are used to split the file into numberK chunks. The other program is FMERGE which requiers one (but will take two) parameters. These are used as the file name base (to merge files) and an optional output file name. Now some back ground: I've compiled and begun testing of both programs. At first they appeared to work perfectly. As far as I can tell, FMERGE still works fine. FSPLIT is giving me problems. When I split files into chunks greater than 30K, I get error 103: File not open at the BlockWrite instruction. When I run again with number of K being 30 or less, the program works fine. I am using Reset(f1,1) and ReWrite(f2,1). My buffer is defined as an array of 1 to MAXBUFFERSIZE of BYTE where MAXBUFFERSIZE is equal to 10240. The guts of the offending code looks like this: FUNCTION FCopy(VAR fIn,fOut :FILE; breakPoint :LONGINT) :BOOLEAN; TYPE BufferType = ARRAY(.1..MaxBufferSize.) OF BYTE; VAR numRead,numWritten :WORD; totalWritten,recsToRead :LONGINT; buffer :BufferType; OK :BOOLEAN; BEGIN OK := TRUE; {OK, I'm an optimis ;-)} totalWritten := 0; IF (breakPoint < SizeOf(Buffer)) THEN recsToRead := breakPoint ELSE recsToRead := SizeOf(buffer); REPEAT BlockRead(fIn,buffer,recsToRead,numRead); BlockWrite(fOut,buffer,numRead,numWritten); totalWritten := totalWritten + numWritten; UNTIL ( (numRead = 0) OR (numRead <> numWritten) OR (EOF(fIN)) OR (numRead < recsToRead) OR (totalWritten >= breakPoint) ); IF (numRead < recsToRead) THEN OK := FALSE; IF (EOF(fIn)) THEN OK := FALSE; IF (numRead <> numWritten) THEN Abort(12,'cannot split file!! Disk is full!!',''); FCopy := OK; END;{FCopy} Well, there it is. I can't figure out why it works for numberK <=30, but not for a larger cut. The buffer size is constant. I must be making a mistake, but can't pinpoint where it is. Those wishing a copy of one or both programs drop me a line and I'll send them out. Any help greatly appre., tom THOMAS E. JENKINS, JR. PROGRAMMER, UNIVERSITY OF SOUTH CAROLINA BITNET, C0361 AT UNIVSCVM.BITNET
milne@ics.uci.edu (Alastair Milne) (06/08/90)
Because I believe this involves a nasty piece of Turbo Pascal protocol, which can trap people very easily, I'm answering this to the net, rather than directly. In <23531@adm.BRL.MIL> C0361%UNIVSCVM.BITNET@ncsuvm.ncsu.edu ( Thomas Jenkins) writes: >FSPLIT is giving me problems. When I split files into chunks >greater than 30K, I get error 103: File not open at the BlockWrite >instruction. When I run again with number of K being 30 or less, the >program works fine. I am using Reset(f1,1) and ReWrite(f2,1). My buffer Unless I am badly mistaken (and I have several pieces of running code to persuade me I'm right), your second parameter here should be the number of bytes per block you want read. Looking immediately below, it looks as if it should be 10240. My usual blocks are only 512, so I don't know how a single BLOCKREAD/WRITE of this size is going to behave, but will agree at least with what you describe here. How did file I/O perform when BLOCKREAD/WRITE were only handling a single byte per block? Which is what I'm sure has been happening from these RESET and REWRITE calls. By the way, remember that your BLOCKWRITE's are going to be writing chunks this size, even when there's much less than that occupying them. So if you read a file that goes, say, 10 bytes into its final bufferload, its chunks are going to be written with a full 10240-byte final block to contain those 10 bytes. I'd suggest 512 bytes, or even just 128, instead. >is defined as an array of 1 to MAXBUFFERSIZE of BYTE where MAXBUFFERSIZE is >equal to 10240. The guts of the offending code looks like this: >BEGIN > .... > REPEAT > BlockRead(fIn,buffer,recsToRead,numRead); > BlockWrite(fOut,buffer,numRead,numWritten); > totalWritten := totalWritten + numWritten; > UNTIL ( (numRead = 0) > OR (numRead <> numWritten) > OR (EOF(fIN)) > OR (numRead < recsToRead) > OR (totalWritten >= breakPoint) ); You are missing calls to IORESULT here. This is very important!! If your IORESULT goes non-zero on any channel, THAT CHANNEL BLOCKS UNTIL IORESULT IS CALLED TO CLEAR IT. (In fact, I'm not sure it doesn't block ALL IO channels). This is one point where I very much disagree with Borland's strategies: a) that calling IORESULT clears it, so you can only call it once after any IO operation; b) that a non-zero status is allowed to suppress all further file operations. By the way, the relationship of IORESULT and NumRead or NumWritten is a bit complicated. Since I don't have it 100% clear myself, I won't try to explain it, but I believe your loop would in any case have to check IORESULT for possible termination, since I don't think IO problems can be detected solely throught NumRead or NumWritten. There may be a couple of other problems here, but I think these are the central ones. I do notice you're comparing TotalWritten to BreakPoint, so either be sure BreakPoint is expressed in blocks, not bytes, or convert one or the other before comparing. > IF (numRead <> numWritten) THEN > Abort(12,'cannot split file!! Disk is full!!',''); You may want to recheck this logic. I'm not sure it's going to work as you want; nor in any case that it would only indicate a disc full. >Well, there it is. I can't figure out why it works for numberK <=30, but not >for a larger cut. ... That number 30K raises another spectre in my mind. Have you perhaps declared as an INTEGER some counter that should be a WORD? Hits 32K and turns negative? I'm afraid I already deleted the declarations you showed above (how embarrassing) so I can't look directly myself. I hope this helps. I think you've got the idea substantially right, and it should work. Alastair Milne, Educational Technology Center, U. Calif. Irvine