Random Access Files

Opening Random Access Files

Purpose:

Random access reads and writes a file in BINARY mode. 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.

Syntax:

OPEN fName FOR BINARY [NEW] AS hFile RECLEN RecordSize

Parameters:

  • Data type: STRING
    fName Name of file to be opened.
  • Data type: Argument
    NEW [OPTIONAL] Used if a new file is being created.
  • Data type: FILE PTR
    hFile A file handle name that identifies the file in subsequent procedure calls, parameter arguments and other circumstances.
    See the File Handle Names section remarks below for details.
  • RecordSize This can be a TYPE structure or an INTEGER variable or literal. RecordSize, optionally, can be separated from RECLEN by an = sign, for example, RECLEN = 1024.

Remarks:

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

If RecordSize is an INTEGER variable or a literal number, that integer must specify the fixed size of the random access record.

👉 If RecordSize is an INTEGER variable, it must be appended with integer data type signifier.

RecordSize is calculated before the value is passed to RECLEN. The programmer is responsible for determining the fixed size of the record.

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:

  • Data type: STRING
    fName name of file to be opened.
  • NEW [OPTIONAL] used if a new file is being created.
  • Data type: FILE
    hFile The handle of the file.
  • Data type: Scalar
    RecordSize can be a TYPE structure, an INTEGER variable (must be appended with a % integer data type sigil) 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 an INTEGER variable (must be appended with % integer data type sigil) 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.

Example:

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

Snip and save the following block of text 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
'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$
  IF x1$ = "" THEN
    PRINT "Exiting now !"
    EXIT LOOP
  END IF
  x% = VAL(x1$)
  RECORD FP1, x
  GET$ FP1, a$, field%
  PRINT a$
LOOP
CLOSE FP1

Result:

RndAcc.txt is fixed record length including the trailing crlf.
               First few lines in the file.
 0000000000:14159265358979323846264338327950288419716939937510
 0000000001:58209749445923078164062862089986280348253421170679
 0000000002:82148086513282306647093844609550582231725359408128
 0000000003:48111745028410270193852110555964462294895493038196
 0000000004:44288109756659334461284756482337867831652712019091
 0000000005:45648566923460348610454326648213393607260249141273
field =  64 numrecs =  19 Last record =  18
Input record number to read 8
 0000000007:78925903600113305305488204665213841469519415116094

Input record number to read 12
 0000000011:60943702770539217176293176752384674818467669405132

Input record number to read
Exiting now !

RECORD statement

Purpose:

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

Syntax:

   RECORD hFile AS FILE, _
RecordNumber AS INTEGER  _
    [, LocationInRecord]

Parameters:

  • Data type: FILE
    hFile The handle of file containing record.
  • Data type: INTEGER
    RecordNumber The record number to which to point. The first record (number 1) is the default.
  • Data type: INTEGER
    LocationInRecord [OPTIONAL] location in record. Default is zero.

Example:

RECORD FP1, 5

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

REC statement

Purpose:

REC returns an integer containing the current record number.

Syntax:

RetVal = REC(hFile AS FILE)

Return Value:

  • Data type: INTEGER
    RetVal Returned integer containing the current record number.

Parameters:

  • Data type: FILE
    hFile The handle of file containing record.

LOC function

Purpose:

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

Syntax:

RetVal = LOC(hFile AS FILE)

Return Value:

  • Data type: INTEGER
    RetVal Returned integer containing the position within the current record.

Parameters:

  • Data type: FILE
    hFile The handle of file containing record.

Example:

👉 For LOC to work correctly the file must to be opened

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.

👉 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 AS FILE)

Return Value:

  • Data type: INTEGER
    RetVal Returned integer containing the number of records in the random access file.

Parameters:

  • Data type: FILE
    hFile The handle of file containing record.

Example:

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