Storages & Files Find
Find method

Binary search through the stream beginning from the current position. Although the binary nature of the Find method it supports text search as well.

This methods allows the application to pass complex data as search pattern. The data is converted to binary sequence of bytes first and then 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 = object.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.
&H00 - After search position on the beginning of the found sequence or stay at the end of stream if nothing has been found.
&H01 - After the search return the original position in the stream - where the search began (even on unsuccessful search). 
&H02 - After the search stay after the found sequence. If nothing is found then stay at the end of stream.
&H04 - 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 &H04 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 stream 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 stream.

Dim main,strm
Set main = Server.CreateObject("newObjects.utilctls.SFMain")
Set strm = main.OpenFile(Server.MapPath("test.bin"))

Do 
    pos = strm.Find(CInt(6),&H02)
    If pos >= 0 Then
        Response.Write "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,strm
Set main = Server.CreateObject("newObjects.utilctls.SFMain")
Set strm = main.OpenFile(Server.MapPath("test.bin"))

Dim a(3)

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

Do 
    pos = strm.Find(a,&H02)
    If pos >= 0 Then
        Response.Write "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,strm
Set main = Server.CreateObject("newObjects.utilctls.SFMain")
Set strm = main.OpenFile(Server.MapPath("test.txt"))

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

Remarks:

About 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 VBScript this can be done by using the CLng, CByte, CStr and the other conversion functions, in JScript use the TypeConvertor component from this library which supplies the same functionality that can be found in VBScript internally but is not available in JScript.

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 stream. 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 stream 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 stream to contain them in an unexpected form.

String searches are always case sensitive.

Applies to: SFStream object

newObjects Copyright 2001-2006 newObjects [ ]