FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

DISK I/O

Parse a DOS file


When getting Information from a MainFrame over a WAN I had line input and input# problems...mainly because of speed. When going through several routers/bridges etc. both were _very_ slow. I went to this type of scheme:

LOCAL
  DIM a,counter
  DIM TheString$
LOCAL FN ReadText$(myLength)
  THESTRING$=""
  counter=0
  FOR counter=1 TO 50 'knew I would never be beyond
'50 so...
    a=PEEK([gCellStrHndl&]+goffset&) 'what is it
    INC(gOffSet&) 'advance
    LONG IF a=13 OR a=9 'checking for Return or Tab
      GOTO "getOut" 'go away without storing it
    END IF
    THESTRING$=THESTRING$+CHR$(a) ' store the CHR$ of it
'in the local string
  NEXT counter
"getOut" 'escape from this puppy
  theString$=LEFT$(theString$,myLength) 'make it nice
END FN=TheString$ 'put it out

LONG IF LEN(gFileName$)
  OPEN "I",#3,gFileName$,,gFileVol
  fileSize&=LOF(3,1) 'figure out how much room you need
  gCellStrHndl&=FN NEWHANDLE(fileSize&) 'get a handle for it
  LONG IF gCellStrHndl&<>_nil 'got the handle
    osErr%=FN HLOCK(gCellStrHndl&) 'parnioa here
    READ FILE#3,[gCellStrHndl&],fileSize& 'here is the speedy part
'get it in one move
    osErr%=FN HUNLOCK(gCellStrHndl&)
    goffset&=0 'set for first char
    gSubAction=0 'no more pg stuff
  XELSE
    osErr%=_mFulErr
    gSubAction=0 'don't go to MainOpen
    FileSize&=-1 'we won't read any data
  END IF
CLOSE #3


WHILE gOffset&<FileSize&
  MyLocal$=FN ReadText$(8)
WEND

Don't forget to do something like this when done with your handle:

IF gCellStrHndl& THEN DEF DISPOSEH(gCellStrHndl&)

I stuck in some comments that weren't there so remember you may have lines that feed (RETURN) strangely if you paste this into a project.

In the line FN ReadText$(8) The length of 8 is because I happen to know I was getting different length strings and I didn't want any overflows. You could cut this out of the routine if you have no need. Sounds like you will be looking at 1 at a time and could do the fix right inside FN ReadText.

And...horror of horrors, I am using a global for the Handle to the text, but I use FN ReadText$ many times in my app. (Can I pass the Handle to a FN ???)

This thing cut one 187K read from 15 minutes on a PB 140 to the blink of an eye. Another 20K read was cut from 147 seconds to 4 seconds via modem to a network.

GB


It would take some work, but if you're willing to use Toolbox routines instead of FB's built-in file-handling functions, then I would recommend doing it like this:

* To read the file contents very quickly:

1. Open the file using FN FSpOpenDF:

OSErr = FN FSpOpenDF(fileSpec, _fsRdPerm, @refNum)

2. Set up a parameter block for reading the file:


DIM iopb.50
handle& = FN NEWHANDLE(_maxLineLength)
LONG IF handle&
  OSErr = FN HLOCK(handle&)
  iopb.ioCompletion& = _nil
  iopb.ioRefNum% = refNum
  iopb.ioBuffer& = [handle&]
  iopb.ioReqCount& = _maxLineLength
  iopb.ioPosMode% = &0D80 'Read up to CR
  iopb.ioPosOffset& = 0 'start at beginning
END IF

Setting the ioPosMode to &0D80 tells it that you want to read up to the next CR character (or up to _maxLineLength characters, or to the end of file, whichever occurs first). Set _maxLineLength to something big like 1000.

3. Then you can read the lines like this:

DO
  OSErr = FN READ(@iopb)
  LONG IF iopb.ioActCount& > 0 'ioActCount& = number of char's read
    FN ProcessTheLine(handle&, iopb.ioActCount&)
  END IF
UNTIL OSErr 'OSErr = _eofErr when end of file reached.

4. Close the file and dispose the handle when you're done:

OSErr = FN CLOSE(@iopb)
DEF DISPOSEH(handle&)

* To find the commas very quickly:

I would recommend that (in FN ProcessTheLine) you pass handle& to FN MUNGER, which is designed to do quick searches on long pieces of text.

Two things to remember:

* The CR at the end of the line is included in the bytes that are read into [handle&].
* If your lines actually are delimited by CR/LF, then the LF will simply show up as the _first_ character on the next line that you read.

Oh, one more thing: FN FSpOpenDF looks like this:

'-----------------------------------------------------------
LOCAL FN FSpOpenDF(@specAddr&, permission, refNumAddr&)
  DIM OSErr
  ` clr.w -(sp)
  ` move.l ^specAddr&,-(sp)
  ` move.w ^permission,-(sp)
  ` move.l ^refNumAddr&,-(sp)
  ` move.w #$0002,d0
  ` dc.w $AA52
  ` move.w (sp)+,^OSErr
END FN = OSErr
'-----------------------------------------------------------

Rick


The following code is to put an item in the handle to new handle. It works well for me. The delimiter of the item can changed easily. At first I tried to read all data to the memory, and then chage the CR+LF to CR, usuing the MUNGER function, then pick up the line with CR delimiter and the pick up each item with commna.

LOCAL FN getItem(hndl&,item%,delimiter$)
  DIM osErr%
  DIM count%,sOfs&,eOfs&,size&,delLen%
  DIM newHndl&,state%

  newHndl& = _nil
  LONG IF hndl&<>_nil
    size& = FN GETHANDLESIZE(hndl&)
    delLen% = LEN(delimiter$)
    count% = 0
    eOfs& = -delLen%
    DO
      INC(count%)
      sOfs& = eOfs&+delLen%
      LONG IF sOfs&<=size&
        eOfs& = FN MUNGER(hndl&,sOfs&,@delimiter$+1,delLen%,_nil,_nil)
      XELSE
        eOfs& = -1
      END IF
    UNTIL count%=item% OR eOfs&<0

    LONG IF count%=item% AND eOfs&<0 AND item%<>1
      eOfs& = size&
    END IF

    LONG IF eOfs&>=0
      size& = eOfs&-sOfs&
      newHndl& = FN NEWHANDLE(size&)
      LONG IF newHndl&<>_nil
        state% = FN HGETSTATE(hndl&)
        osErr% = FN HLOCK(hndl&)
        osErr% = FN HLOCK(newHndl&)
        BLOCKMOVE [hndl&]+sOfs&,[newHndl&],size&
        osErr% = FN HUNLOCK(newHndl&)
        osErr% = FN HSETSTATE(hndl&,state%)
      END IF
    END IF
  END IF
END FN = newHndl&