DI Management Home > Cryptography > Byte Arrays in VB6 Visual Basic

Byte Arrays in VB6 Visual Basic


To carry out cryptographic operations in classic Visual Basic (VB6 and VBA) we should use the unambiguous Byte type instead of the much more convenient String type. This page shows how to handle arrays of the Byte type compared to the simpler operations we know how to do with the String type.

To doStringByte Array
Dimension
Dim str As String
' Dynamic array of n bytes (0,1,...,n-1)
Dim abArray() As Byte
' ...
ReDim abArray(n-1)

' OR for a static array
Dim abArray(n-1)

' or, more explicitly,
Dim abArray(0 To n-1)
Assign
str = "xxxx"

' OR (can be slow for long strings)
For i = 1 To n
    str = str & "x"
Next

' OR (faster)
str = String (' ', n)
For i = 1 To n
    Mid(str, i, 1) = "x"
Next
For i = 0 To n - 1
    abArray(i) = x
Next

' OR (safer)
For i = LBound(abArray) To UBound(abArray)
    abArray(i) = x
Next
Access the ith element
Dim ch As String
ch = Mid(str, i, 1)
Dim b as Byte
b = abArray(i - 1)
Convert ith element
Dim b As Byte
b = Asc(Mid(str, i, 1)) 
Dim ch As String
ch = Chr(abArray(i - 1))
Length
Dim nLen As Long
nLen = Len(str)
Dim nLen As Long
nLen = UBound(abArray) - LBound(abArray) + 1
Compare
If str1 = str2 Then ...
' (Fudge, but works)
If StrConv(abArray1, vbUnicode) = _
    StrConv(abArray2, vbUnicode) Then ...
See Comparing Byte arrays below.
Copy
Dim str1 As String
Dim str2 As String
str1 = "..."
str2 = str1
Dim ab1() As Byte
Dim ab2() As Byte
' ...assign data to ab1...
ab2 = ab1

' OR, assuming ab1 has been assigned,
Dim i As Long
ReDim ab2(UBound(ab1))
For i = LBound(ab1) To UBound(ab1)
    ab2(i) = ab1(i)
Next
Concatenate
Dim str1 As String
Dim str2 As String
Dim str3 As String
str1 = "..."
str2 = "..."
str3 = str1 & str2
Dim ab1() As Byte
Dim ab2() As Byte
Dim ab3() As Byte
Dim i As Long
' ...assign data to ab1 and ab2...
ab3 = ab1
ReDim Preserve ab3(UBound(ab1) + UBound(ab2))
For i = 0 To UBound(ab2)
    ab3(i + UBound(ab1)) = ab2(i)
Next
Is Empty
If str = "" Then ...

' OR (better)
If Len(str) = 0 Then ...
On Error GoTo EmptyArray
nLen = UBound(abArray) - LBound(abArray) + 1
' If got here then array is not empty
' ...
EmptyArray:
' ...will jump to here if empty

' OR create this useful function
' that returns zero if the array is empty
Public Function BytesLength(abBytes() As Byte) As Long
    ' Trap error if array is empty
    On Error Resume Next
    BytesLength = UBound(abBytes) - LBound(abBytes) + 1
End Function
Return from a function
Dim str As String
str = MyStrFunc()
'
Public Function MyStrFunc() As String
    MyStrFunc = "A string"
End Function
Dim abArray() As Byte
abArray = MyByteFunc()
'
Public Function MyByteFunc() As Variant
    Dim i As Long
    Dim abBytes() As Byte
    ReDim abBytes(n-1)
    For i = 0 To n-1
    	abBytes(i) = x
    Next
    MyByteFunc = abBytes
End Function

' CAUTION: Do not dimension abArray as a static array
' e.g.
Dim abArray(5) As Byte	' static array
abArray = MyByteFunc()	' NO! Will cause a run-time error.
See also Returning a Byte array value from a function below.

Notes

  1. The byte array examples assume that Option Base 0 is the default.
  2. The dimensioning of byte arrays in VB6 is a trap for programmers used to C and Java, and is counter-intuitive. An array of n bytes is dimensioned as
    	Dim abArray(n-1)
    
    That is the n-byte array [abArray(0), abArray(1), ..., abArray(n-1)]. You still use indexes For i = 0 To n-1 like in C, but you dimension the size of the array differently. If you use Dim abArray(n) you have an extra byte at the end, which will come back to "byte" you (sorry). A more intuitive way is to use the full, formal expression
    	Dim abArray(0 To n-1)
    
  3. Always dimension your index variables as Long. If you use Integer it will seem to work OK until one day you have data that is longer than 32767 and you will get a run-time error. There must be a corollary of Simpson's Law here:
    All tests you can ever think of doing, or at least can be bothered doing, will involve an integer less than SMALL_INT_MAX, but one of your users will use SMALL_INT_MAX + 1 within one day of production release.

Returning a Byte array value from a function

To return a Byte array from a function, dimension the function as a Variant type.
Public Function MyByteFunc(Input) As Variant
    Dim abBytes() As Byte
    Dim nLen as Long
    nLen = CalcLen(Input)
    ReDim abBytes(nLen - 1)
    For i = 0 To nLen - 1
    	abBytes(i) = x
    Next
    MyByteFunc = abBytes
End Function
and explicitly cast the return value back to a (dynamic) Byte array in the calling function.
Dim abArray() As Byte
abArray = MyByteFunc(X)
Debug.Print "Array Length=" & UBound(abArray) + 1
'...
But if you need to return an error condition before you ReDim the abBytes array, you will get a run-time error when you try to read the returned value.
Public Function MyByteFuncBad(Input) As Variant
    Dim abBytes() As Byte
    Dim nLen As Long
    If IsError(Input) Then
    	Exit Function
    End If
    nLen = CalcLen(Input)
    ReDim abBytes(nLen - 1)
    For i = 0 To nLen - 1
    	abBytes(i) = x
    Next
    MyByteFuncBad = abBytes
End Function
Dim abArray() As Byte
abArray = MyByteFuncBad(X)
Debug.Print "Array Length=" & UBound(abArray) + 1  ' RUN-TIME ERROR!. 
To solve, use this trick
Public Function MyByteFuncGood(Input) As Variant
    Dim abBytes() As Byte
    Dim nLen As Long
    ' Set default return value that won't cause a run-time error
    MyByteFuncGood = StrConv("", vbFromUnicode)
    If IsError(Input) Then
    	Exit Function
    End If
    nLen = CalcLen(Input)
    ReDim abBytes(nLen - 1)
    For i = 0 To nLen - 1
    	abBytes(i) = x
    Next
    MyByteFuncGood = abBytes
End Function
Dim abArray() As Byte
abArray = MyByteFuncGood(X)
Debug.Print "Array Length=" & UBound(abArray) + 1  ' Should return 0 on error. 
We've not seen this trick of using StrConv with an empty string documented anywhere. We discovered it by accident. But it works.

Comparing Byte arrays

To compare two Byte arrays, you can use the one-line StrConv fudge we suggest above. To do a strict comparison for equality, you can use the following function, which assumes both byte arrays have been dimensioned.
Public Function ByteArraysAreEqual(data1() As Byte, data2() As Byte) As Boolean
On Error GoTo OnError
    Dim i As Long
    ByteArraysAreEqual = False
    If UBound(data1) <> UBound(data2) Then
        Exit Function
    End If
    For i = LBound(data1) To UBound(data1)
        If data1(i) <> data2(i) Then
            Exit Function
        End If
    Next i
    ByteArraysAreEqual = True
Done:
    Exit Function
OnError:
    Resume Done
End Function

Contact

To comment on this page or ask a question, please send us a message.

This page last updated 27 February 2013