Streaming
Home
Introduction
Philosophy
General techniques
Sorting
Searching
Factory
Persistence
Logging
Streaming
Tokenizers
Parsing
File Searching
Command
PseudoPatterns
Compiling
Downloads
FeedBack

Streaming

Streams are a natural part of C++ for a long time. Unfortunately, VB doesn’t seem to offer a real alternative.  To handle that, I wrote some very simple classes.

    Requirements : “Write some classes to allow for files and strings to be handled transparently for sequential input and output purposes.”

IOutputStream

An output stream is something to which you can write characters. Because of its text-based nature, we introduce a NewLine method too.  The interface looks like this :

Interface IOutputStream
Public sub WriteString (byval aVal as string)
Public sub NewLine
Public sub Flush

Write dumps the characters to the stream.  NewLine is semnatically a new line (allthough a stream may choose to do that in a different way). Flush makes sure internal buffers are cleared.

I created two obvious implementations : cOutputStreamFile and cOutputStreamString. The file implementation goes like this :

Private mFileHandle         As Integer
Private mbCloseOnTerminate As Boolean

Implements iOutputStream

Friend Sub Initialize(ByVal nHandle As Integer, ByVal bCloseOnTerminate As Boolean)
  mFileHandle = nHandle
  mbCloseOnTerminate = bCloseOnTerminate
End Sub

Private
Sub Class_Initialize()
  mFileHandle = -1
  mbCloseOnTerminate = True
End
Sub

Private
Sub Class_Terminate()
  If mbCloseOnTerminate Then Close #mFileHandle
  mFileHandle = -1
  mbCloseOnTerminate = False
End
Sub

Private
Sub iOutputStream_Flush()
  Flush
End Sub

Private
Sub iOutputStream_NewLine()
  Print #mFileHandle,
""
End Sub

Private
Sub iOutputStream_WriteString(ByVal aVal As String)
  Print #mFileHandle, aVal
; ' semicolon does the trick
End Sub

The string class is also straightforward.  It uses mid$ to do efficient concatenations and is a publicNotCreateable class to allow a user to retrieve the accumulated value.

Next to these implementations, I also wrote cOuputStreamImmediate (which will dump to the immediate window), cOutputStreamNull (NullObject pattern), cOutputStreamMultiPlex (writes to several streams at once).  These are more or less standard things, so I will not discuss them further.

For all of them I created facade methods to allow for an easy creation.  To write one string to a file you would do :

CreateOutputStreamFile("c:\hello.txt")
                     .writeString("Hello world")

There are currently no implementations for sockets, allthough writing them should prove easy.  There are also currently no filtered stream decorators. I will write them when I need them.

Just as a proof of concept, I wrote an “encrypting” stream decorator.  The purpose is no so much the encrypting algorithm, which is a simplistic Caesar encryption, but more to hint at the power of streams.

    IInputStream

    Input streams are much harder to define. It is much harder to come up with a meaningful and sufficient interface for input streams. Here is what I came up with.

    Property Get EOF() As Boolean
    Sub ReadCharacters(ByRef strCharacters As String,
                       ByVal nCountToRead As Long)

    The interface is minimal but even then it requires some explanation. EOF returns whether we are at the end of the stream. ReadCharacters reads at most nCountToRead characters. If there are any characters left in the stream and the stream is not a the end then this function returns at least one character. When the stream is at the end it always returns an empty string.

    Like outputstreams, I also wrote the two “standard implementations” : a string input stream and a file input stream.  Here is the code for the file input stream :

    Private mFileHandle         As Integer
    Private mbCloseOnDelete    As Boolean
    Implements IInputStream

    Friend Sub Initialize(ByVal nFileHandle As Integer, ByVal bCloseOnDelete As Boolean)
      mFileHandle = nFileHandle
      mbCloseOnDelete = bCloseOnDelete
    End Sub

    Private
    Sub Class_Initialize()
      mFileHandle = -1
      mbCloseOnDelete = False
    End
    Sub

    Private
    Sub Class_Terminate()
      If mbCloseOnDelete Then
         Close #mFileHandle
         mbCloseOnDelete = False
      End If
      mFileHandle = -1
    End Sub

    Private
    Property Get IInputStream_EOF() As Boolean
      IInputStream_EOF = EOF(mFileHandle)
    End Property

    Private
    Sub IInputStream_ReadCharacters(strCharacters As String, ByVal nCountToRead As Long)
      Dim nCountToGo    As Long
     
      If EOF(mFileHandle) Then
         strCharacters =
    ""
         Exit Sub ' ---------------------->
      End If
     
      nCountToGo = LOF(mFileHandle) - Seek(mFileHandle) + 1
      If nCountToRead > nCountToGo Then nCountToRead = nCountToGo
      strCharacters = Input(nCountToRead, #mFileHandle)
    End Sub

    This concludes the discussion on streams.

    Subitems :

     

     

    Site updated : Monday, February 17, 2003