Tech Note 08a: Files with Records and Fields
|
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. |
Indexed property that returns a field from the record.
Set variable = Record.Field(index)
Record.Field(index) = value
index - String or number. The name or index of the field in the record, starting from 1.
' Will list the fields names and their values For I = 1 To Record.Count MsgBox record.Field(I).Name & " = " & record.Field(I) Next
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.
Returns the count of the fields in the record.
variable = Record.Count
AddObject "newObjects.utilctls.SFRecord", "Record" Record.AddField "FirstName", vbString, 20 Record.AddField "LastName", vbString, 20 MsgBox "Field count " & Record.Count ' Will return 2
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.
Record.Add Name, Type[, Size]
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.
'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
Removes a field from the record.
Record.Remove index
index - String or numeric. Field name or index to remove.
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
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.
Binds the Record to a file. Binding occurs through the default filter or through an optional filter.
Record.BindTo File [, filter]
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.
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
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.
Re-binds the record to the same file with the same filter. Can be called only if BindTo was called before.
Record.ReBind
See Read.
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.
Removes the binding from the record.
Record.UnBind
See Read.
This must be called when you close the file, otherwise it will still be around when you open it again.
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.
variable = Record.RecordCount
Record.RecordCount = variable
variable - the number of records in the file.
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"
The RecordCount property gets/sets the number of the records in the file calculated over the file size.
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
variable = Record.Move pos, origin
variable = Record.MoveNext
variable = Record.MovePrev
variable = Record.MoveLast
variable = Record.MoveFirst
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.
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 fileExample 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 dataExample 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.
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.
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).
variable = Record.ReRead
returned value: Boolean success indicator
You may need this method in different situations:
- To ensure the record's content is synched with the contents of the file
- To refill the record if you have change the position in the file explicitly (not through the record's navigation methods)
- To discard the values set to the record after the last navigation/read operation.
Updates the file with the record contents. The file and record position remains the same - over the same record.
variable = Record.Update
returned value: Boolean success indicator.
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
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.
Reads the record from the current position in the file and leaves the current position after it.
variable = Record.Read
variable - Boolean value - True if successful, False if not successful or if the end of file has been reached.
'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
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.
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.
variable = Record.Write
returned value: Boolean success indicator
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
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.