User Tools

Site Tools


Command disabled: register
reading_20and_20writing_20arrays_20in_20files

Reading and writing arrays in files

by Jon Ripley, May 2011

Alternative method added by Steve Drain, Oct 2013

BBC BASIC for Windows does not provide a simple method of writing arrays to a file and reading them back again, doing so traditionally requires looping through the array and saving each separate item individually.

The PROC_ReadArray and PROC_WriteArray routines below provide equivalents to PRINT# and INPUT# for arrays and are faster than the traditional method in most cases.

        PROC_WriteArray(fileHandle%, ^array())
        PROC_ReadArray(fileHandle%, ^array())


When reading and writing arrays you must prefix the array variable name with the address of operator, the ^ symbol, this allows us to pass all types of array to a single routine rather than requiring a separate routine for each.

PROC_WriteArray writes the contents of an array to the file specified by fileHandle%.

        DIM array(9, 9, 9, 9)
        REM Initialise array
        fileHandle% = OPENOUT("data.dat")
        PROC_WriteArray(fileHandle%, ^array())
        CLOSE#fileHandle%


PROC_ReadArray reads data from the file specified by fileHandle% and stores it in the specified array.

        DIM array(1000, 10)
        fileHandle% = OPENIN("data.dat")
        PROC_ReadArray(fileHandle%, ^array())
        CLOSE#fileHandle%


For more information about PROC_SwapMemory see swapping the contents of two areas of memory.

The full code for PROC_ReadArray, PROC_WriteArray and PROC_SwapMemory is as follows:

        DEF PROC_WriteArray(file%, parr%):LOCAL write%:write%=TRUE
        DEF PROC_ReadArray(file%, parr%):LOCAL write%
        LOCAL i%, tele%, esize%, temp%
        IF NOT (parr%?-1 = 0 AND parr%?-2 = 40) THEN
          ERROR 6, "Type mismatch: Bad array pointer"
          ENDPROC
        ENDIF
 
        tele%=1
        FOR i%=0 TO ?!parr%-1
          tele%*=!((!parr%+1)+(4*i%))
        NEXT i%
 
        CASE parr%?-3 OF
          WHEN ASC"%":esize%=4
          WHEN ASC"#":esize%=8
          WHEN ASC"$":esize%=6
          WHEN ASC"&":esize%=1
          OTHERWISE:esize%=5
        ENDCASE
 
        PTR#file%=PTR#file%
        IF parr%?-3 <> ASC"$" THEN
          IF write% THEN
            SYS "WriteFile", @hfile%(file%), !parr%+1+?!parr%*4, tele%*esize%, ^temp%, 0
          ELSE
            SYS "ReadFile", @hfile%(file%), !parr%+1+?!parr%*4, tele%*esize%, ^temp%, 0
          ENDIF
        ELSE
          LOCAL temp$()
          DIM temp$(tele%-1)
          PROC_SwapMemory(!^temp$()+1+?!^temp$()*4, !parr%+1+?!parr%*4, tele%*esize%)
          IF write% THEN
            FOR i%=0 TO tele%-1:PRINT#file%, temp$(i%):NEXT i%
          ELSE
            FOR i%=0 TO tele%-1:INPUT#file%, temp$(i%):NEXT i%
          ENDIF
          PROC_SwapMemory(!^temp$()+1+?!^temp$()*4, !parr%+1+?!parr%*4, tele%*esize%)
        ENDIF
        ENDPROC
 
        REM PROC_SwapMemory(addr1%, addr2%, size%)
        REM Suggested by Richard Russell
        DEF PROC_SwapMemory(B%, D%, C%)
        PRIVATE memswap
        IF memswap=0 THEN
          LOCAL P%
          DIM memswap 10
          P%=memswap
          [OPT 2
          mov al,[ebx]
          xchg al,[edx]
          mov [ebx],al
          inc ebx
          inc edx
          loop memswap
          ret
          ]
        ENDIF
        CALL memswap
        ENDPROC
 


Thanks to Richard Russell for the SwapMemory function.


Alternative method


This method writes information about the type of array and its size in the file and checks that it it the same when reading. It does not require the SwapMemory assembler code.

The API is the same as the routines above, except, when reading:

  • the number of elements in the target array must be equal to the file array, but the array can be a different shape
  • a string target array must be empty


        DEF PROC_WriteArray(file%,pntr%)
        LOCAL type%,size%,numb%,temp%
        PROC_ArrayData
        BPUT#file%,type%
        REM write the number of elements as a word
        BPUT#file%,numb%
        BPUT#file%,numb%>>8
        BPUT#file%,numb%>>16
        BPUT#file%,numb%>>24
        REM flush the buffer
        PTR#file%=PTR#file%
        IF type%=ASC"$" THEN
          FOR pntr%=pntr% TO pntr%+numb%*size%-1 STEP size%
            BPUT#file%,pntr%?4
            BPUT#file%,pntr%?5
            size%=pntr%?4+(pntr%?5<<8)
            PTR#file%=PTR#file%
            SYS"WriteFile", @hfile%(file%),pntr%,size%,^temp%,0
          NEXT pntr%
        ELSE
          SYS"WriteFile", @hfile%(file%),pntr%,numb%*size%,^temp%,0
        ENDIF
        ENDPROC
 
        DEF PROC_ReadArray(file%,pntr%)
        LOCAL type%,size%,numb%,temp%
        PROC_ArrayData
        IF type%<>BGET#file% THEN ERROR 6,"Wrong array type"
        REM read the number of elements as a word
        temp%=BGET#file%
        temp%+=BGET#file%<<8
        temp%+=BGET#file%<<16
        temp%+=BGET#file%<<24
        IF numb%<>temp% THEN ERROR 6,"Wrong array size"
        REM flush the buffer
        PTR#file%=PTR#file%
        IF type%=ASC"$" THEN
          FOR pntr%=pntr% TO pntr%+numb%*size%-1 STEP size%
            IF pntr%?4 OR pntr%?5 THEN ERROR 6,"String array not empty"
            pntr%?4=BGET#file%
            pntr%?5=BGET#file%
            size%=pntr%?4+(pntr%?5<<8)
            DIM !pntr% size%
            PTR#file%=PTR#file%
            SYS"ReadFile", @hfile%(file%),pntr%,size%,^temp%,0
          NEXT pntr%
        ELSE
          SYS"ReadFile",@hfile%(file%),pntr%,numb%*size%,^temp%,0
        ENDIF
        ENDPROC
 
        DEF PROC_ArrayData
        IF pntr%?-2<>ASC"(" THEN ERROR 6,"Not an array"
        type%=pntr%?-3
        CASE type% OF
          WHEN ASC"%":size%=4
          WHEN ASC"#":size%=8
          WHEN ASC"$":size%=6
          WHEN ASC"&":size%=1
          OTHERWISE:type%=ASC"|":size%=5
        ENDCASE
        pntr%=!pntr%
        numb%=1
        FOR temp%=pntr%+1 TO pntr%+?pntr%*4 STEP 4
          numb%*=!temp%
        NEXT temp%
        pntr%=temp%
        ENDPROC
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
reading_20and_20writing_20arrays_20in_20files.txt · Last modified: 2018/04/17 18:24 by tbest3112