StreamingStreams 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.”
IOutputStreamAn 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. |