Tech Note 08: File Control

April 02, 2008


This control is used to read and write files. It is included with 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.

Background: This control replaces the MSCEFile control in NS Basic/CE and the FileSystemObject (FSO) in NS Basic/Desktop. Code written using this control is interoperable between both NS Basic products.

The File I/O Control is used to read and write data in files. It is useful for files where entire records are read or written in string or binary format. If you would like to read and write your records as separate fields, have a look at Tech Note 8a "File I/O with Fields".

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.

Comma separated files (csv) can be easily handled by this control. Use the ReadText function to read in the entire record, then do a Split(record, ",") function to break it into its array of variables.

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"
Set File = FS.OpenFile("C:\MyFile.txt")
Size Size of the file
Pos Position in the file (in bytes)
textLineSeparator Text line separator (defaults to the windows standard)
unicodeText Text access as UNICODE (True) or ANSI (False). Default is ANSI
codePage If unicodeText is False this specifies the code page used for text conversion. 
EOS Becomes True if the end of file is reached
maxTextBuff Maximum buffer size for the text lines. 
stats Gets the file information (name, size, times etc.)
ReadBin Reads binary data and returns it as array of bytes packed in a variant.
WriteBin Writes binary data
Seek Changes/obtains the current position in the File.
CopyTo Copies from this file to another.
ReadText Reads text from the file (line, specified number of characters or the entire file)
WriteText Writes text to the File.
Close Releases/closes the File.
Find Binary search through the file beginning from the current position.

Size

Returns the size of the file or resizes it. The size is in bytes.

Syntax:

variable = File.Size
File.Size = newSize

Remarks:

When read the property returns the total size of the file in bytes. Writing the property allows the application to truncate or enlarge the File.


Pos

Gets/sets the absolute position of the File.

Syntax:

variable = File.Pos
File.Pos = variable

Position 1 or more: the byte index in the File. 

Remarks:

If positioned beyond the end the file is automatically enlarged.

The Seek method provides extended navigation tasks.

See also: Seek


textLineSeparator

Defines the text line separator. This allows the ReadText method to recognize the lines in text files and WriteText to write correct lines when called with 1 option.

Syntax:

File.textLineSeparator = variable
variable = File.textLineSeparator

The default value is the Windows default line separator - vbCrLf

Remarks:

The separator can be used in different ways depending on the option used with the ReadText and WriteText methods. See their options for more information. 

The line delimiter cannot exceed 16 characters.


unicodeText

Set/get Unicode text manipulation option for the File. This option tells the File object how to read and write text.

Syntax:

File.unicodeText = boolean
variable = File.unicodeText

The default value is False (Ansi).

Remarks:

If the property is true all the text methods will use unicode when reading or writing. If False, the text will be converted using the code page specified by the CodePage property.


codePage

Specifies the code page used for text operations when configured to use ANSI text.

Syntax:

File.codePage = value
variable = File.codePage

Default is: cpAnsi (ANSI code page)

Parameters:

    Const   cpAnsi                  =   0   ' ANSI code page 
    Const   cpOem                   =   1   ' OEM code page
    Const   cpMac                   =   2   ' MAC code page
    Const   cpSymbol                =   42  ' Symbol code page
    
    'Specific code pages - if they are not installed on the system conversions will fail
    Const   cpThai                  =   874
    Const   cpJapanese              =   932
    Const   cpChinese               =   936
    Const   cpKorean                =   949
    Const   cpChinese2              =   950
    Const   cpEasternEuropean       =   1250
    Const   cpCyrillic              =   1251
    Const   cpWestern               =   1252
    Const   cpGreek                 =   1253
    Const   cpTurkish               =   1254
    Const   cpHebrew                =   1255
    Const   cpArabic                =   1256
    Const   cpBaltic                =   1257

Remarks:

Code page specifies how the text is converted from/to ANSI characters (more precisely UNICODE to/from multibyte conversions).

See also: ReadText.


EOS

Indicates it the end of the file is reached. 

Syntax:

variable = File.EOS

True value means the current position is at or after the end of File.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
' Open exiting text file
' Read it line by line
While Not File.EOS
  MsgBox File.ReadText(-3)
Wend

Remarks:

Pay attention to the methods that change the file position. The file position is changed by: ReadText, WriteText, WriteBin, ReadBin, Pos, Seek.


maxTextBuff

Specifies the maximum size of the internal buffer used for text operations (mostly the read operations).

Syntax:

File.maxTextBuff = value
variable = File.maxTextBuff

Positive number (in bytes). Default is 1048576 bytes (1 meg).

Remarks:

Usually 1 megabyte buffer will be enough for reading lines or other portions of the file as text. If you expect bigger portions to be read/written at once set this property to a greater value.  


stats

Returns info object for the File.

Syntax:

Set info = File.stats

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
Set info = File.stats
MsgBox "Last accessed: " & info.Accessed
MsgBox "Last modified: " & info.Modified

Remarks:

The members of info are:

ReadBin

Reads the number of bytes specified.

Syntax:

variable = File.ReadBin(bytes)

Parameters:

bytes - integer number specifying the number of bytes to read.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
bin = File.ReadBin(100)
' Reads 100 bytes from the file

Remarks:

The bytes read are packed in a VARIANT binary array (VT_ARRAY | VT_UI1). The result can be passed to any property or method expecting binary data. You can pass the result directly to the WriteBin method.

If the end of file is reached during the read operation the number of the bytes returned will be less than the number of bytes requested.


WriteBin

Writes binary data to the File.

Syntax:

variable = File.WriteBin(data)

Parameters:

data - The data to write to the File. As usual in all similar methods the binary data is expected to be array of bytes (i.e. VT_ARRAY | VT_UI1).

returned value - the number of bytes written to the File.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
nBytes = File.WriteBin(someBinaryData)
File.Close

Seek

Implements navigation through the file (more extended than the functionality supplied by the Pos property)

Syntax:

variable = File.Seek( position, origin)

Parameters:

position - positive or negative numeric value - the position to navigate to

origin - a constant, specifies how to calculate the physical position over the supplied position parameter. The constants are:

0 Position must be positive and specifies the file position (in bytes) calculated from the beginning of the File. 
1 Position can be positive or negative. The file position is moved forward (positive) or backwards (negative) from the current file position. 
2 Calculated from the end of File. Positive values will enlarge the file size. 

returned value: The resulting absolute position of the File. 

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
File.Seek(10,0)
' Going to the 10-th byte in the file
MsgBox File.ReadText(5)
' Read 5 characters
' Skipping 10 more bytes after the last read character
pos = File.Seek(10,1)
' pos contains the absolute resulting position

Remarks:

The control supports files no greater than 2GB in size.

Note that using the file with SFRecord object bound allows you to navigate the file through the SFRecord object (with record based positioning instead of byte based). However using the Seek method may give you advanced options - to skip some non-standard records or work with files/files which contain records and other data in some of its parts.


CopyTo

Copies the entire file or portion of it to the target File.

Syntax:

variable = File.CopyTo( file, cbBytes)

Parameters:

file - the Target File.

cbBytes - Bytes to copy to the target File.

returned value: The actual number of bytes copied.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File1 = FS.OpenFile("C:\MyFile1.txt")
Set File2 = FS.OpenFile("C:\MyFile2.txt")
File1.Pos = 100
n = File1.CopyTo(File2,100)
' Copies 100 bytes beginning from the 100-th byte in the
' source File.

Remarks:

This method can be used for fast transfer of data between different files.

Used to copy files from different storages - for example file to a file in an OLE file etc.


ReadText

Reads text from the file (from the current position).

Syntax:

variable = File.ReadText(numChars)

Parameters:

positive number - the specified number of characters will be read.
negative numbers have special meaning:
-2 - The entire file (or remaining portion of it depending on the current position) is read as single string
-1 - One line of text is read. The text line is assumed to end with the line separator as it is specified by the
textLineSeparator property.
-3 - Advanced version of the previous (-1). This reads one line but applies more heuristic logic - recommended if you work with text files created by unknown operating system (e.g. the line separator can be different). See remarks.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
' Open exiting text file
' Read 10 characters
MsgBox File.ReadText(10)
' Read one line (non-heuristic)
MsgBox File.ReadText(-1)
' Read one line (heuristic)
MsgBox File.ReadText(-3)
' Read the remaining file as whole
MsgBox File.ReadText(-2)

Remarks:

The text is assumed UNICODE or ANSI depending on the unicodeText property.

When -1 (cReadLine) constant is used the line is assumed to end with the line separator exatcly as it is specified in the textLineSeparator property. Other combinations will not be recognized. However this option does not require file to be seekable (see Seek) and can be used on any file object - external or built-in.

When -3 (cReadLineAny) is used the file should be seekable and the end of line is detected more carefully. The line is assumed to end with any of the characters in the string specified by the textLineSeparator property. It is assumed that the line separator may contain more characters but there are no duplicated characters in it. The method automatically skips the rest of the delimiter using this rule and positions there. Method is proved to work correctly with all the popular text files (MAC, UNIX, Windows). The default setting for the textLineSeparator is good text files coming from MAC, UNIX, Windows.


WriteText

Writes string to the file at the current position and remains after the last character written.

Syntax:

File.WriteText string [, option]

Parameters:

string - The string to write to the file

option - Defines how the text will be written:
0 (default) - just write the string "as is"
1 - Write the string and place "new line" separator after it.

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
' Write the string
File.WriteText "Hello "
' Write the rest of the string and place end-of-line
File.WriteText "world!",1

Remarks:

The string will be written using ANSI or UNICODE depending on the unicodeText property. The line seprator is specified by the textLineSeparator property.


Close

Releases the file attached to the File.

Syntax:

File.Close

Parameters:

none

Examples:

AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.txt")
bin = File.ReadBin(100)
File.Close

Remarks:


Find

Binary search through the file beginning from the current position. The binary nature of the Find method means it supports text search as well.

This methods allows the application to pass complex data as search patterns. The data is converted to binary sequence of bytes and the actual search is performed. If several alternative sequences are to be searched the method can be instructed to search for any of them (but they must have the same length). See the remarks for details.

Despite the complex features supported by the method there are simple and complex ways to use it. You can choose what suits your needs best.

Syntax:

variable = File.Find(what [, flags [, chunkSize]])

Parameters:

what - What to search for. A variant parameter that accepts almost any possible value and converts it to binary sequence. See the remarks for detailed description.

flags - optional, default is 0. How to perform the search. Appropriate combinations of the following flags can be specified.
0 - After search position on the beginning of the found sequence or stay at the end of file if nothing has been found.
1 - After the search return the original position in the file - where the search began (even on unsuccessful search). 
2 - After the search stay after the found sequence. If nothing is found then stay at the end of File.
4 - Find any of the specified chunks. If specified the chunkSize parameter is taken into account if not specified it will be ignored. 

chunkSize - optional, default is 0. Takes effect only if 4 is specified in the flags parameter. In this case the byte sequence which is result of conversion of the what parameter to binary is separated into chunks with length chunkSize bytes and each chunk is searched separately. If one of them is found the method returns its position. Note that if the size is specified so that the last chunk is smaller than the others this last chunk will be ignored.

returns: the position in the file if successful or -1 if unsuccessful (nothing found). 

Examples:

Search for the short integer values of 6. It will appear (on x86 based Windows systems) as 00 06 in the binary File.

Dim main,strm
AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.bin")

Do 
    pos = File.Find(CInt(6),&H02)
    If pos >= 0 Then
        MsgBox "Found at Pos = [" & pos & "]<BR>"
    End If
Loop Until pos < 0

Search for something more complicated - two textual parts with and binary data between them. For simplicity we search two words - first is at the end of line the second must be in the beginning of the next line in a text File. But this technique can be used for any sequence.

Dim main,File
AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.bin")

Dim a(3)

a(0) = "First"
a(1) = CByte(AscB(vbCr))
a(2) = CByte(AscB(vbLf))
a(3) = "Second"

Do 
    pos = File.Find(a,2)
    If pos >= 0 Then
        MsgBox "Found at Pos = [" & pos & "]<BR>"
    End If
Loop Until pos < 0

This piece of code will search for all the occurrences of the words "Cat" and "Dog" in the File. File can be a text file or some kind of binary File.

Dim main,File
AddObject "newObjects.utilctls.SFMain", "FS"
Set File = FS.OpenFile("C:\MyFile.bin")

Do 
    pos = File.Find("CatDog",&4,3)
    If pos >= 0 Then
        MsgBox "Found at Pos = [" & pos & "]<BR>"
        File.Pos = File.Pos + 1
    End If
Loop Until pos < 0

Remarks:

what parameter: The application can pass basic variant types (as numeric values or string) and arrays of them. The data contained in the parameter is converted into binary sequence of bytes. Thus if you pass a binary data it will be used "as is". If string is passed it will be converted as the unicodeText and codePage specify and the result will be treated as sequence of bytes. In case of strings the terminating null character is ignored (this is a binary search method we cannot rely on no preliminary assumption how the strings are recorded in it or you can search partial string etc.). The array passed may contain variants in turn (but not other arrays). This is probably the most useful form for the scripts - it allows you to pass different values which will be converted properly and concatenated into single binary sequence used further.

Note that objects cannot be passed to the method through the what parameter! There is no way to determine how to convert them - thus their default property cannot be resolved. So when using values contained in objects (and most likely in their default properties) the application is responsible to convert them to basic values. In NS Basic this can be done by using the CLng, CByte, CStr and the other conversion functions.

If you are feeling confused by the above requirement consider one example situation - an object with a default property which will return a number, for example 7. Converting it to string and then passing it to this method will result in one byte containing the ASCII code of the character '7' (or two bytes in UNICODE mode), but if you convert it to long integer first (using CLng function) it will result in 4 bytes sequence. Thus the resulting binary sequence searched will be different. This illustrates why there is no way to resolve the default properties of the objects in the method itself.

How the non-string values are converted?  They are used as they appear in the memory. If you need complete control on each byte pass array of bytes or array of variants where the important bytes are carefully converted to VT_BYTE subtype by using CByte. 

What will happen if you pass array of several strings? All the strings will be converted and concatenated. Then depending on the flags if chunks are used the result will be separated in chunks or searched as whole if chunks  feature is not used. 

Mixing strings with other data. If you are searching for a byte sequence that consist of  textual parts and binary parts - you can describe it by creating an array where the text parts are strings and the non-string parts are represented by elements holding numeric data (bytes for example). This allows the scripting application to specify any possible byte sequence even if the script language itself is not capable of doing so.

It is recommended to use bytes and strings mostly. Do not forget that the longer numeric values can be represented in different manner in the File. For example a short integer value (two bytes) can be represented as the high byte first or contrary its low byte can be first in the memory representation. This depends on how and where the file has been created. Therefore using non-byte numeric values requires you to consider their representation in the memory and evaluate if it is possible the file to contain them in an unexpected form.

String searches are always case sensitive.