by Jon Ripley, July 2006

The technique described in the storing structures in files article does not work for structures containing strings or string arrays. In most cases it is easier simply to write the individual structure members to file one at a time using PRINT# and read them back again using INPUT# or READ#. This alternative method is required to load and save structures containing strings using ReadFile and WriteFile.

Why? BBC BASIC for Windows does not store the strings themselves inside the structure, instead strings are represented as a string descriptor - a pointer to the string data and the length of the string. This means that the strings must be written to and read from the file separately from the structure block. Due to how string allocation works in BBC BASIC each string must be cleared before writing to the file, if strings were left intact then you may crash BBC BASIC when you later load the structure and copy the strings back into the structure. Temporary variables are used to contain the strings whilst the structure is being saved.

Writing the structure

To copy the strings into temporary variables, which should be made LOCAL inside your save routine, and clear the strings use code similar to the following:

      temp1$ = struct.string1$
      temp2$ = struct.string2$
      struct.string1$ = ""
      struct.string2$ = ""

Here each string in the structure is copied into a temporary string and each string in the structure is set to a NULL string (""). It is now safe to write the structure and the string data to the file:

      PTR#file% = temp%
      SYS "WriteFile", @hfile%(file%), struct{}, !!^struct{}, ^temp%, 0
      PRINT#file%, temp1$, temp2$...

Here the file buffers are flushed, the structure is written to the file and the temporary copy of each string is written to the file.

To copy the strings back into the structure use code similar to the following:

      struct.string1$ = temp1$
      struct.string2$ = temp2$

Reading the structure

To load the structure from the file use code similar to the following:

      PTR#file% = PTR#file%
      SYS "ReadFile", @hfile%(file%), struct{}, !!^struct{}, ^temp%, 0
      INPUT#file%, struct.string1$, struct.string2$...

Here we flush BASIC's file buffers, call ReadFile to read the structure from the file and use INPUT# to load the strings from the file.