RANDOMFile.md 9.2 KB

Using Random Access Files

Random access records are stored differently from sequential access records. A random access record has a fixed length as does each field within the record. The fixed length determines the beginning and end of each record or field. Random access reads and writes a file in BINARY mode.

Two main keywords are used in random access, RECLEN and RECORD.

RECLEN statement

Purpose: RECLEN is used at the end of an OPEN file statement to calculate the fixed length of the random access record.


 Syntax:

 OPEN fName$ FOR BINARY [NEW] AS hFile RECLEN RecordSize

 Parameters:

  • fName$ Name of file to be opened.
  • NEW [OPTIONAL] Used if a new file is being created.
  • hFile Handle to the file.
  • RecordSize TYPE structure, an INTEGER variable(must be appended with % integer data type signifier) or an INTEGER literal. RecordSize optionally can be separated from RECLEN by an = sign, for example, RECLEN = 1024.

    If RecordSize is a TYPE structure, RECLEN will calculate automatically the size of the TYPE structure.

    If RecordSize is INTEGER variable(must be appended with % integer data type signifier) or a literal number, that integer must specify the fixed size of the random access record. RecordSize is calculated before the value is passed to RECLEN. The programmer is responsible for determining the fixed size of the record.

The program below, RndAcc.bas, is an example that calculates the size of the record. RndAcc.bas OPENS an existing text file in BINARY mode and reads random access records from the file.

 
 '-----------Begin snip and save as RndAcc.txt-----------------
 0000000000:14159265358979323846264338327950288419716939937510
 0000000001:58209749445923078164062862089986280348253421170679
 0000000002:82148086513282306647093844609550582231725359408128
 0000000003:48111745028410270193852110555964462294895493038196
 0000000004:44288109756659334461284756482337867831652712019091
 0000000005:45648566923460348610454326648213393607260249141273
 0000000006:72458700660631558817488152092096282925409171536436
 0000000007:78925903600113305305488204665213841469519415116094
 0000000008:33057270365759591953092186117381932611793105118548
 0000000009:07446237996274956735188575272489122793818301194912
 0000000010:98336733624406566430860213949463952247371907021798
 0000000011:60943702770539217176293176752384674818467669405132
 0000000012:00056812714526356082778577134275778960917363717872
 0000000013:14684409012249534301465495853710507922796892589235
 0000000014:42019956112129021960864034418159813629774771309960
 0000000015:51870721134999999837297804995105973173281609631859
 0000000016:50244594553469083026425223082533446850352619311881
 0000000017:71010003137838752886587533208381420617177669147303
 0000000018:59825349042875546873115956286388235378759375195778
 0000000019:18577805321712268066130019278766111959092164201989
 '-------------End snip and save as RndAcc.txt-----------------

 'RndAcc.bas Random file access of a ASCII text file

 CLS
 DIM a$,x%,x1$,lenf%,i%,numrecs%,field%
 PRINT "RndAcc.txt is fixed record length including the trailing crlf."
 OPEN "RndAcc.txt" FOR INPUT AS FP1
 LINE INPUT FP1,a$
 CLOSE FP1
 field% = LEN(a$)+2
 lenf% = LOF("RndAcc.txt")
 
 OPEN "RndAcc.txt" FOR INPUT AS FP1
 PRINT "               First few lines in the file."
 FOR i% = 0 TO 5
   LINE INPUT FP1 , a$
   PRINT a$
 NEXT
 CLOSE FP1
 
 OPEN "RndAcc.txt" FOR BINARY AS FP1 RECLEN field%
 numrecs% = lenf%/field%
 PRINT "field = ";field%;" numrecs = ";numrecs%;" Last record = ";numrecs%-1
 DO
   INPUT "Input record number to read ",x1$
   x% = VAL(x1$)
   RECORD FP1,x
   GET$ FP1,a$,field%
   PRINT a$
 LOOP UNTIL x1$ = ""
 CLOSE FP1
 

RECORD statement

Purpose: RECORD is used to move a pointer within the file to a specific record.


 Syntax:

 RECORD hFile, RecordNumber [,Location IN RECORD] 

 Parameters:

  • hFile Handle to file containing RECORD.
  • RecordNumberRECORD number to which to point. The first record(number 1) is the default.
  • Location in record [OPTIONAL] location in RECORD. Default is Zero.

For example,

RECORDFP1, 5

would move the pointer to the fifth record in the file.

REC function

Purpose: REC returns an integer containing the current record number.


 Syntax:

 RetVal% = REC(hFile)

 Parameters:

  • hFile Handle to file containing RECORD.
  • RetVal% Returned integer containing the current record number.

LOC function

Purpose: LOC returns an integer containing the position of a pointer within the current record.


 Syntax:

 RetVal% = LOC(hFile)

 Parameters:

  • hFile Handle to file containing RECORD.
  • RetVal% Returned integer containing the position within the current record.

Note well, that for LOC to work correctly the file must to be opened with a RECLEN , for example


 OPEN "Data.bin" FOR BINARY AS FP1 RECLEN Datar

 RECORD FP1, 5   'move to the beginning of the 5th record
 x = LOC(FP1)
 'x would be equal to 0

 RECORD FP1, 5, 10  'move to the 10th character in the 5th record
 x = LOC(FP1)
 'x would be equal to 10

RECCOUNT function

Purpose: RECCOUNT returns an integer containing the number of records in the random access file.

Note well that after RECCOUNT has been called, the file pointer is left at the end of the file. The REC and LOC functions could be used to determine and save the current position of the file pointer before calling RECCOUNT and then, after RECCOUNT has been called, the saved REC and LOC values could be used as arguments in a RECORD function call to move the file pointer back to the original record and position.


 Syntax:

 RetVal% = RECCOUNT(hFile)

 Parameters:

  • hFile Handle to file containing RECORD.
  • RetVal% Returned integer containing the number of records in the random access file.

Here is an example of writing and reading a Random Access file.


 'Simple Random Access database
  
 DIM inpt$
 DIM str1$
 DIM FileName$
  
 TYPE DATAREC
   FName [10] AS CHAR
   MName [10] AS CHAR
   LName [10] AS CHAR
   Age AS INTEGER
 END TYPE
 
 DIM Datar AS DATAREC
 
   INPUT "Filename of database to open ? ", FileName$
  
   IF EXIST(FileName$) THEN
     OPEN FileName$ FOR BINARY AS FP1 RECLEN Datar
   ELSE
     INPUT "File does not exist. Create?(Y/N)", str1$
     IF UCASE$(str1$) = "Y" THEN
       OPEN FileName$ FOR BINARY NEW AS FP1 RECLEN Datar
     ELSE
       CLOSE
       END
     END IF
   END IF
  
 jmp1:
 PRINT "Press 0 to quit"
 PRINT "Press 1 to add record"
 PRINT "Press 2 to get record"
 INPUT inpt$
  
 IF inpt$ = "0" THEN
   GOTO finis
 END IF
  
 IF inpt$ <> "1" AND inpt$ <> "2" THEN
   GOTO jmp1
 END IF
  
 IF inpt$ = "1" THEN
   CALL AddRecord()
 END IF
  
 IF inpt$ = "2" THEN
   CALL GetRecord()
 END IF
  
 GOTO jmp1
  
 finis:
   CLOSE FP1
 END
  
 SUB AddRecord()
   LOCAL AddRec$
   LOCAL RecNum%
  
   DO
     RecNum% = RECCOUNT(FP1)
     PRINT "Database contains"; STR$(RecNum%); " records."
  
     INPUT "Add record number ", RecNum%
     RECORD FP1, RecNum
  
     INPUT "First Name ", Datar.FName$
     INPUT "Middle Name ", Datar.MName$
     INPUT "Last Name ", Datar.LName$
     INPUT "Age ", Datar.Age%
  
     PUT$ FP1, &Datar, SIZEOF(Datar)
  
     INPUT "Add another record(Y/N)? ", AddRec$
     RecNum% ++
  
   LOOP UNTIL UCASE$(AddRec$) = "N"
  
 END SUB
  
 SUB GetRecord()
   LOCAL GetRec%
   LOCAL RecNum%
  
   DO
     INPUT "Get record number(0 to quit) ", GetRec%
     IF GetRec% = 0 THEN
       EXIT LOOP
     END IF
  
     RECORD FP1, GetRec
     GET$ FP1, &Datar, SIZEOF(Datar)
  
     PRINT Datar.FName$
     PRINT Datar.MName$
     PRINT Datar.LName$
     PRINT Datar.Age%
   LOOP
 
 END SUB