Tech Note 08a: Files with Records and Fields

October 1, 2009


This control provides an easy way to access files which have their data organized in records and fields. It is included in NS Basic. The information in the document is for the most part copied from the official documentation on NewObject's website. For further information, please refer to the official documentation. The information on this page is copyright ZmeY soft and published with their permission.

Code written using this control is interoperable between both NS Basic/CE and NS Basic/Desktop.

If the data in your file is organized as one or more records, with a single string or binary data in each record, use the File I/O control in Tech Note 08. If your file has a fixed format to each record, File I/O with fields as described in this Tech Note should be used.

The methods and properties documented here are a subset of the full capabilities of this control. To see the rest of the features, look at the full documentation from NewObjects. The features not included here will still work well with NS Basic, but are for advanced users.

The Record object defines a record of values of well-known types. This record then can be saved or read to/from any file. The effect is a technique very similar to the technique used with the DB tables but applicable to files. If you ever heard of or used flat files or files with random access - this is the way to do so.

How does this work? The script defines a record - i.e. defines its fields and defines their types and sizes. With types known for each field the size of the entire record can be calculated - e.g. how many bytes it will occupy.

Then the NS Basic program is able to set the record's fields with values or read them. To read/write the record from/to file or other file the application connects the Record object with the file (see BindTo method). With this, the application sees the file as set of records. The application can move the current position to any record and read or write it. Thus the file behaves as table of records. It is similar to the tables in a DB, but note the difference - the record definition is created by the script and not obtained from the file (of course - if the file contains such information the program could read it and create the record).

Before any of the items below can be used, the file needs to be opened. Do this using the OpenFile method in the File System Control.

Installation: This control requires that NewObjectsPack1.dll be installed and registered.

Creation:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set File = FS.OpenFile("C:\MyFile.txt")

Record definition members
Field (default) Access field of the record
Count Count of the fields in the record
AddField Create and add a new field to the record
Remove Remove a field from the record
Connection to file (and filter)
BindTo Bind the record to a file through a filter specified or using the default filter.
ReBind Rebind to the file. If come fields are added/removed/changed
UnBind Remove the binding.
Random access (DB table-like) reading and writing
RecordCount The total records in the file
Move, MoveNext, MovePrev, MoveFirst, MoveLast Recordset like operations.
ReRead Rereads the record from the file.
Update Saves (updates) the record to the file.
Sequential read/write
Read Reads the record from the file. The new position is immediately after the record. 
Write Writes the record to the file. The new position is after the record.

Field

Indexed property that returns a field from the record.

Syntax:

Set variable = Record.Field(index)
Record.Field(index) = value

Parameters:

index - String or number. The name or index of the field in the record, starting from 1.

Examples:

' Will list the fields names and their values
For I = 1 To Record.Count
   MsgBox record.Field(I).Name & " = " & record.Field(I)
Next

Remarks:

This property gives the application access to the previously added fields into the record. It supports names and numeric indexes therefore the fields can be accessed sequentially and directly (by known name) as needed.


Count

Returns the count of the fields in the record.

Syntax:

variable = Record.Count

Examples:

AddObject "newObjects.utilctls.SFRecord", "Record"
Record.AddField "FirstName", vbString, 20
Record.AddField "LastName", vbString, 20
MsgBox "Field count " & Record.Count
' Will return 2

Remarks:


AddField

Creates and adds new field to the record. This methods provides a convenient way to construct a record when the fields are well-known and several fields are to be added sequentially.

Syntax:

Record.Add Name, Type[, Size]

Parameters:

Name - name of the new field (string)

Type - The type of the new field. One of the vbXXtype constants for example (see VarType function in NS Basic Language Reference for list of the constants).

Size - Optional integer value that specifies the size/maximum size of the field value. Required only for data types like strings.

Examples:

  'Add a field named "Title" of String type with size 128 characters
  Record.AddField "Title", vbString, 128
  
  'Add a field named "Age" of type Integer (2 bytes integer)
  Record.AddField "Age", vbInt
  

Remarks:


Remove

Removes a field from the record.

Syntax:

Record.Remove index

Parameters:

index - String or numeric. Field name or index to remove.

Examples:

Suppose the file contains one type of records up to a certain position and another after it.

  AddObject "newObjects.utilctls.SFMain", "FS"
  AddObject "newObjects.utilctls.SFRecord", "Record"
  Set file = FS.OpenFile("Somefile.bin")
  Record.AddField "FirstName", vbString, 20
  Record.AddField "LastName", vbString, 20
  Record.BindTo file
  Record.MoveFirst
  For I = 1 To 4
    ' Do something, display records etc.
    Record.MoveNext
  Next
  Record.Remove "FirstName"
  Record.ReBind
  For I = 1 To 4
    ' Do something, display records etc.
    Record.MoveNext
  Next
  ' 4 records containing first and last name are read and then
  ' 4 records containing only last name

Remarks:

As in the other cases after changing the record structure/settings ReBind must be called in order to allow the filter to re-calculate the record representation. Of course the modified record can be attached to another file - by calling BindTo with the other file as parameter.


BindTo

Binds the Record to a file. Binding occurs through the default filter or through an optional filter.

Syntax:

Record.BindTo File [, filter]

Parameters:

Record - an initialized SFRecord Record. There is no sense to invoke BindTo without some Fields added to the record.

File - An object representing a file.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "A", vbString, 20
Record.AddField "B", vbLong
Record.AddField "C", vbDouble
Record.BindTo file 

Remarks:

Binding creates or/and attaches a record to a file.

Be sure to UnBind before closing the file.

If any settings of the record are changed the ReBind method must be called in order to calculate the correct size of the record.

The optional filter argument provides additional specifications on how the data is read and written. You can read additional documentation here.


ReBind

Re-binds the record to the same file with the same filter. Can be called only if BindTo was called before.

Syntax:

Record.ReBind

Examples:

See Read.

Remarks:

ReBind must be invoked any time a change is made to the record object settings. This excludes the changes of the field values, of course.

Be sure to UnBind before closing the file.


UnBind

Removes the binding from the record.

Syntax:

Record.UnBind

Examples:

See Read.

Remarks:

This must be called when you close the file, otherwise it will still be around when you open it again.


RecordCount

When read this property returns the total count of the records in the file. They are calculated over the current file size, the size of the record and the beginning of the file.

When written the property sets the file size to the number of records specified. Therefore setting RecordCount to a number less than the current actual record count will truncate the file. Respectively setting it to a greater value will extend the file.

Can be called only if the record has been previously bound to a file.

Syntax:

variable = Record.RecordCount

Record.RecordCount = variable

Parameters:

variable - the number of records in the file.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "FirstName", vbString, 20
Record.AddField "LastName", vbString, 20
Record.BindTo file
MsgBox "The file contains " & Record.RecordCount & " records"

Remarks:

The RecordCount property gets/sets the number of the records in the file calculated over the file size.


Move, MoveFirst, MoveNext, MovePrev, MoveLast

Record based navigation through the file. These methods supply features similar to the DB recordsets. The position in the file is changed to the record specified and the record object is read (filled with the data contained in the file at the position). Previously contained data in the record is lost (if not explicitly written before the move operation).

MoveFirst - moves current position to the first record
MoveLast - moves the position over the last record (or the beginning of the file if empty)
MoveNext - moves to the next record
MovePrev - moves to the previous record

Syntax:

variable = Record.Move pos, origin
variable = Record.MoveNext
variable = Record.MovePrev
variable = Record.MoveLast
variable = Record.MoveFirst

Parameters:

variable - Boolean. Indicates the success of the operation - True means success, False means failure.

pos - Position in the file - index of the record in the file where the record object is to be positioned.

origin - How the pos is calculated against:

0 - the beginning of the file
1 - the current record. E.g. negative pos will move the record backwards and positive will move it forward.
2 - the end of the file.

Examples:

Example 1:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "FirstName", vbString, 20
Record.AddField "LastName", vbString, 20
Record.BindTo file
Record.MoveFirst
MsgBox record.Field("FirstName") & " " & record.Field("LastName")
' Will display the first record from the file

Example 2:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "FirstName", vbString, 20
Record.AddField "LastName", vbString, 20
Record.BindTo file
Record.Move 0, 2
record.Field("FirstName") = "John"
record.Field("LastName") = "Smith"
Record.Write
' Moves the record immediately after the end of the file
' In other words creates new record and sets and writes some data

Example 3:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "FirstName", vbString, 20
Record.AddField "LastName", vbString, 20
Record.BindTo file
Record.MoveFirst
k = 1
While Not File.EOS
  MsgBox "Record " & k & ": " & record.Field("FirstName") & " " & record.Field("LastName")
  Record.MoveNext
  k = k + 1
Wend
' Lists all the records from the file.

Remarks:

The behavior of the Record object resembles the behavior of a recordset object (like in ADO or DAO), but there are considerable differences caused by the fact that Record works over files and not over a data base. There are some actions automatically performed by the recordsets used with data bases, but in case of files the application is responsible for everything. We designed the Record object to require as little additional work as possible without losing functionality.

Move methods change the current position in the file. After moving the record is read from the file and position is recovered (i.e. the record remains positioned on the same record). To change the contents of the record at the current position in the file application changes the values of the record's fields and calls the Update method - to update the file.

When moving the data already contained in the record is not saved (this is the typical behavior of all the similar objects - DB recordsets for example).

One important note for Record. After binding (e.g. call the BindTo or ReBind methods) the record is not positioned, nor read, nor written from/to the file. Therefore the position of the record in the file is not guaranteed. To ensure the record is positioned on the first record call MoveFirst (or other method if another position is desired) before doing anything else. However the position is not changed by rebind operations and if before performing the operation the record has been positioned you will need to call only the ReRead method to synchronize the data in the file and in the record.

Creating new record in the file is equivalent to moving the current position after the last record. Therefore it can be done by calling Record.Move 0,2 and not MoveLast which will move the position over the last existing record.


ReRead

Re-reads the record from the current position in the bound file and remains on the SAME record (the position after the method call will be the same as before calling it).

Syntax:

variable = Record.ReRead

Parameters:

returned value: Boolean success indicator

Remarks:

You may need this method in different situations:


Update

Updates the file with the record contents. The file and record position remains the same - over the same record.

Syntax:

variable = Record.Update

Parameters:

returned value: Boolean success indicator.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "Field1", vbString, 20
Record.AddField "Field2", vbLong
Record.BindTo file

Record.MoveFirst
For I = 1 To 10
  record.Field("Field1").Value = "Value " & I
  record.Field("Field2").Value = I
  Record.Update
  Record.MoveNext
  MsgBox "Writing record " & I
Next
Record.UnBind

Remarks:

It is helpful to compare the sample above with the sample in the Write method's page.

The update operation is implemented in a way very similar to the similar methods in ADO and many other DB manipulation API/components. In fact after defining and binding the record to the file the usage of the Record object follows the same pattern.


Read

Reads the record from the current position in the file and leaves the current position after it.

Syntax:

variable = Record.Read

Parameters:

variable - Boolean value - True if successful, False if not successful or if the end of file has been reached.

Examples:

'1. Read all the records up to the end of the file.
While Record.Read
  MsgBox record.Field("field1") & ", " & record.Field("field2") & "<BR>"
Wend
'2. Read the contents of the file sequentially
AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "Field1", vbString, 20
Record.AddField "Field2", vbLong
Record.BindTo file
Record.Filter.unicodeText = False
Record.ReBind

While Not file.EOS
  Record.Read
  MsgBox "Read a record: Field1=" & record.Field("Field1").Value & " ,Field2=" & record.Field("Field2").Value
Wend
Record.UnBind

Remarks:

Read and Write methods are alternatives to the Move, ReRead and Update methods.

The record must be bound to the file. If the input data is not Unicode, the Filter.UnicodeText property needs to be set to False (default is True) and a ReBind done.


Write

Writes the contents of the record to the file and remains on the resulting position - i.e. the position after the operation is the next record. 

Syntax:

variable = Record.Write

Parameters:

returned value: Boolean success indicator

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
AddObject "newObjects.utilctls.SFRecord", "Record"
Set file = FS.OpenFile("Somefile.bin")
Record.AddField "Field1", vbString, 20
Record.AddField "Field2", vbLong
Record.BindTo file

For I = 1 To 10
  record.Field("Field1").Value = "Value " & I
  record.Field("Field2").Value = I
  Record.Write
  MsgBox "Writing record " & I 
Next
Record.UnBind

Remarks:

It will be helpful to compare the sample above with the sample in the Update method's page.

The Write method does not need its own seek (re-positioning operation).

As it can be seen using Write method instead of update requires a bit less code and is perfect for initial file filling operations. For example a program that imports a DB table into file, may prefer the Write method which will simplify its code.