[comp.lang.pascal] Turbo Pascal error : HELP!

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