Find a String Within A Stream

There are a couple of ways to code this one. The method below perferms consistently over large streams. The other method (which I may show here also) works faster on small streams. Basically we're just finding a string within a stream.

Back to Code Samples

//===========================================================================
/// <summary>
/// An example method used to locate a string within a stream.
/// </summary>
/// <remarks>This method will not return if the end of stream is never reached and the string
/// for which we're searching has not been found.</remarks>
/// <param name="stringToFind">The string to locate within the stream.</param>
/// <param name="stream">The stream to read.</param>
/// <returns>True if the string is found, false if the end of stream is reached and string is not located. This method will not return
/// until the entire stream is searched for the string. The stream position will be set to the last character in the match if found,
/// lest it will be positioned at the last character in the stream.</returns>
//===========================================================================
public bool FindString_Unbuffered(string stringToFind, Stream streamToRead)
{
// Check the string argument.
//TODO: Verify this is the desired behavior. Should we throw an ArgumentException instead?
if (String.IsNullOrEmpty(stringToFind))
return false;

// Check the stream argument.
//TODO: Verify this is the desired behavior. Should we throw an ArgumentException instead?
if (streamToRead == null || !streamToRead.CanRead)
return false;

if (streamToRead.Length < stringToFind.Length)
return false;

int stringCompareIndex = 0;

BinaryReader reader = new BinaryReader(streamToRead);

byte[] stringToFindBytes = StreamEncoding.GetBytes(stringToFind);
byte currentByte;

while (true)
{
try
{
currentByte = reader.ReadByte();
}
catch (EndOfStreamException) {
return false;
}

// If we find a matching character in this position and we have found all the characters,
if (currentByte == stringToFindBytes[stringCompareIndex])
{
if (++stringCompareIndex >= stringToFindBytes.Length)
{
return true;
}
}
else if (stringCompareIndex > 0)
{
// Rewind so that we restart one further than the last match block.
reader.BaseStream.Seek(-stringCompareIndex, SeekOrigin.Current);
stringCompareIndex = 0;
}
}
}

Back to Code Samples