Classic Computer Magazine Archive COMPUTE! ISSUE 92 / JANUARY 1988 / PAGE 80

Flexible Files

Jeff Klein

Arm yourself with all the information you need to make the IBM PC's BASICA random file commands even more powerful. Your file structures will be limited only by your imagination. For the PC with BAS1CA, compatibles with GW-BASIC, or the PCjr with Cartridge BASIC.

After working with BASICA's random access files, you're bound to run into problems which limit your file structure. If you use a large number of fields, program lines can become too large for the BASICA editor to handle. Difficulties can also arise if you want to allow the user to define the file structure, and using arrays as record names can be a laborious task. This article presents techniques that allow you to create a completely flexible file structure. Long and complex program lines no longer become necessary. Self-modifying file structures can be created. Structures required by a database—where different file structures are demanded for each application—are now possible, as well as structures which may require change over time. In fact, almost any imaginable file structure is possible.

Random Access Files

First, let's briefly review random access files. The random access file is a file in which a group of information, called a record, can be accessed by its position in the file. This position is called its record number. In contrast, a sequential file can be accessed only by starting at the first record and reading each record until the desired one is located.

Random access file structures are defined by the OPEN and FIELD statements. The OPEN statement has the following format:

OPEN "filename" AS #filenum
  LEN = reclength

This opens a file named filename using filenum as its reference number, with each record having a length of reclength. The format of the FIELD statement is as follows:

FIELD #filenum, fldlength AS stgvar, …

This statement defines the structure of the file with the reference number filenum. Here the first field has a length fldlength which will be assigned to the string variable stgvar. A list of lengths and string variables, separated by commas, can continue to define the entire file structure. The file must be open before its fields can be defined, so the OPEN statement must be used before the FIELD statement.

A file is accessed with the GET and PUT statements:

PUT #filenum, recnum
GET #filenum, recnum

PUT writes to a file, and GET reads from it. The record number recnum will be read or written to the file filenum.

Before you can store a record, however, it must be moved into the file buffer. This is done with the LSET or RSET statements. The format for these statements is as follows:

LSET stgvar = stgdata
RSET stgvar = stgdata

These commands move the data stgdata, which is a string, into the file buffer in the field defined by stgvar. LSET left-justifies the data, and RSET right-justifies it. Be sure to use the variable names represented by stgvar only in combination with the LSET and RSET statements while the file is open. Failure to do this stops any data from entering the file buffer for that field name.

Defining A Flexible File

The key to a flexible file structure lies in the FIELD statement. This fact is the key: All FIELD statements executed for a file are operating simultaneously. That is, FIELD statements do not cancel each other out.

This suggests that a record can be divided differently in separate FIELD statements. Thereafter, each time the record is read in, it is partitioned in the way it was divided by each FIELD statement.

For example, Figure 1 demonstrates how to split a record into overlapping fields. The file is opened with a record length of 40 characters. The first FIELD statement divides the record into three fields; the second, into five. When the GET command is executed, record 5 is read, dividing the record two ways.

This means that in Figure 2, DUM$ will contain the characters specified in the last FIELD statement when a record is read in.

Flexible Arrays

Arrays can be defined using this same technique. Again, a dummy variable DUM$ absorbs the previously defined fields. The idea is to step through the record, assigning each array element its own FIELD statement. At each step, the unwanted or previously assigned fields are absorbed into the unused variable DUM$. Figure 3 is an example of this technique that can be adapted directly into your own programs. Notice that the record length must be calculated to open the file.

Designing Your Own Fife

Completely nonstandard files can be created in much the same way, as shown in Figure 4. The format for the file is stored, in this case, in an array. Each element holds the length of a field. A separate variable contains the number of fields defined. These can be assigned from a file, read in from DATA statements, or input from the user.

Before the file can be opened, the record length must be calculated. Line 10 does this by adding the individual field lengths stored in the array. The file is then opened, and the fields are defined. This is done in a loop, using the same technique described earlier for arrays. This time, however, the length of fields must be summed manually to produce the number of characters to absorb the next time through the loop (see line 60). Again, these statements can be adapted into your own programs.

Please note: If you are planning to use a record length of more than 128 bytes (characters) you must initialize BASIC differently. The file buffer size is changed by adding parameters to the BAblC command when loading BASIC. The command with its relevant parameters is

BASICA /F: number-of-files /S : buffersize

By default, the buffer size is 128 characters, and the maximum number of files is eight. The maximum buffer size is 32,767 characters. This means that your flexible file cannot have a record length larger than 32767. This should not be a problem, however. If you find yourself running out of memory with a large buffer size, limit the maximum number of files (you probably won't be reading and writing to eight files simultaneously). Here is an example of initializing BASIC with two open files and a record length of 150 characters.

BASICA /F:2 /S : 150

Figure 1

1st FIELD statement→DATEDESCRIPTIONPRICE
record 5 :"06/14/87#356Color Monitor280.00"(sample)
2nd FIELD statement→MDYRITEM
OAEE
NYAF
TR
H
10 OPEN "example1.dat" AS #1 LEN = 40
20 FIELD #1, 8 AS DATE$, 25 AS  DESCRIPTION$, 7 AS PRICES
30 FIELD #1, 2 AS MONTH$, 1 AS DUM$, 2 AS DAY$, 1 AS DUM$
2 AS YEAR$, 1 AS DUM$, 3 AS REF$, 21 AS ITEM$
7 AS DUM$
40 GET #1, 5

Figure 2

record 14 :"103040204587342323393861"(sample)
ABCD(line 20)
DUM$EFGH(line 30)
(final assignment of)DUM$IJKL(line 40)
10 OPEN "example2.dat" AS #2  LEN = 36
20 FIELD #2, 3 AS A$, 3 AS B$, 3 AS C$, 3 AS D$
30 FIELD #2, 12 AS DUM$, 3 AS E$, 3 AS F$, 3 AS G$, 3 AS H$
40 FIELD #2, 24 AS DUM$, 3 AS I$, 3 AS K$, 3 AS K$, 3 AS L$
50 GET #2, 14

Figure 3

record 18,"342003451535"(sample)
DUM$A$(l)1st pass (loop)
DUM$A$(2)2nd pass
DUM$A$(3)3rd
DUM$A$(4)4th
DUM$A$(5)5th
DUM$A$(6)6th
DUM$A$(7)7th (last)
(final assign of)DUM$
Note: In this example  FIELDLEN = 3
                       NUMARRAYS = 7
10 OPEN "example3.dat" AS #3 LEN = FIELDLEN*NUMARRAYS
20 FOR I-1 TO NUMARRAYS
30 FIELD #3,(I-1)*FIELDLEN AS DUM$, FIELDLEN AS A$(I)
40 NEXT I
50 GET #1, 18

Figure 4

1234
1234567890123456789012345678901234567890
record 34:"-----------------------------------------------------------------------"
file structure :wantassign
field of length 5FIELDLEN(l) = 5
field of length 7FIELDLEN(2) = 7
field of length 10FIELDLEN(3) = 10
field of length 9FIELDLEN(4) = 9
field of length 9FIELDLEN(5) = 9
in this caseFIELDNUM = 5
10 RECLEN = 0 : FOR I = 1 TO  FIELDNUM : RECLEN = RECLEN + FIELDLEN(I) : NEXT I
20 OPEN "example4.dat" AS #4 LEN = RECLEN
30 DUMLEN = 0
40 FOR I = 1 TO FIELDNUM
50 FIELD #4, DIMLEN AS DUM$, FIELDLEN(I) AS A$(I)
ODUMlEN = DUMLEM + FIELDLEN (I)
70 NEXT I
80 GET #4, 34