• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 311
  • Last Modified:

Shifting Byte arrays?

Experts...I need to shift a byte array say 10, 20 or whatever number of elements up to make room for other information such as a header.  How can I do this WITHOUT using a loop of some kind.  CopyMemory?  Sample code that works please...

PS  It's gotta be really FAST
  • 8
  • 6
  • 3
  • +2
1 Solution
This could be very easy if you happen to be using VB6

In VB6 you are allowed to assign the value of a byte array to a string and vice versa.

Simply move your byte array to a string, concatenate the 10 characters and move it back.
I think the questioner meant something else. He want to move memory.

Here is a sample:
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

 Call CopyMem(udtVerBuffer, ByVal lplpBuffer, Len(udtVerBuffer))

JohnnAuthor Commented:
What I want to do is "insert" bytes to the beginning of an existing byte array, not append...
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Hello Mirkwood,

As I read the question, Johnn's byte array might contain something line "ABC" (looking at byte array as if it were a string)

Now what Johnn wants to do is insert 10 "blanks" before:
"          ABC" so that he has room to put in some "header" information.

In VB6 this can be achieved like I said.

Johnn, if you haven't got VB6 I think Mirkwood's suggestion might be the best alternative.
"concatenate the 10 characters"

or of course:

concatenate it to 10 characters (to insert it before)

It could be that the byte array is a string but you never know.
Btw: VB5 support also the assigning byte array to string and vice versa as far as I rememeber. The problem with this that this is different under NT and win95 because of unicode.

JohnnAuthor Commented:
The solution you posted(VB5 works as well) works for all strings, however I'm mixing string and numeric data.  No that I've played with the idea I might want something like this...
dim myByte() as byte
redim myByte(0 to 3)'four byte long header info, aka length of string
'now I want to "append" to this byte array a string, how do we do it without a loop? OR we could build the string byte array first and then insert this in front...
JohnnAuthor Commented:
How does that unicode affect things?  Which os uses which?  From my tests(win95), assigning a string to a byte array doubles it which is not something I want(I know it recreates it properly, but we could be talking alot of loop cycles here)
It depends on your string and OS.
In general win95 uses 1 byte characters
and winnt uses 2 byte characters
JohnnAuthor Commented:
are you sure you didn't get the two os' mixed up?  I'm using win95 and my bytearrays were double the size of the string.
Hello Johnn,

Can you reject my answer please - it looks like Mirkwood is getting close to having a solution for you.
JohnnAuthor Commented:
as requested, although neither is close yet...
>>How does that unicode affect things?

Unicode uses a word (16 bits = TWO bytes) for each character.

VB5 Internally uses unicode or at least 2-byte strings: See following code.
This code prefixes 4 bytes to an existing byte array. But to make sure I set sensible data I set the first two bytes to 65 and 0 (making up a capital A in unicode) and the second two bytes to 66 and 0 (making up a capital B)

Dim barTEST() As Byte
Dim barTEST2(1 To 4) As Byte

Dim strTEST1 As String
Dim strTEST2 As String

strTEST2 = "Hello"
barTEST = strTEST2

MsgBox barTEST

barTEST2(1) = 65
barTEST2(2) = 0
barTEST2(3) = 66
barTEST2(4) = 0
strTEST1 = barTEST2

strTEST2 = strTEST1 & strTEST2
barTEST = strTEST2

MsgBox barTEST

PS - I'm running Windows NT 4.0 + SP3

I think my suggestion does work after all. Check this out:

Option Explicit

Private Sub Command1_Click()

'Give barOriginal an odd number of bytes to prove that _
 even though internal VB strings are supposedly unicode _
 (i.e. 2 bytes per character) this will not impact on how _
 the strings can be used to manipulate whole byte arrays _
 in one go.
Dim barOriginal(1 To 3) As Byte
Dim barNew() As Byte
Dim strWork As String
Dim strWork2 As String

'Give the individual elements some odd values which would _
 not make up decent string characters to prove that even _
 that will not cause any problems.
barOriginal(1) = 1
barOriginal(2) = 0
barOriginal(3) = 3
strWork = barOriginal
strWork2 = barOriginal
strWork = strWork & strWork2
barNew = strWork

MsgBox (barNew(0))
MsgBox (barNew(1))
MsgBox (barNew(2))
MsgBox (barNew(3))
MsgBox (barNew(4))
MsgBox (barNew(5))

'Original byte array had only 3 elements so concatenating _
 it to itself makes a total of 6 elements so this next _
 one (the 7th) creates a subscript out of range error.
MsgBox (barNew(6))

End Sub

If you want it fast, and you don't need any Wide character, use this mapping:
1 character (2 bytes) <-> 1 byte
Using CopyMemory is >2x faster than copying array members.

Paste this to your form:

Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, source As Any, ByVal bytes As Long)
Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dest As Any, ByVal bytes As Long)
Dim myByte() As Byte

Private Sub Form_Click()
    ReDim myByte(0 To 5) 'four byte long header info, aka length of string
    myByte(0) = 1
    myByte(1) = 1
    myByte(2) = 5
    myByte(3) = 5
    myByte(4) = 7
    myByte(5) = 7
    'we could build the string byte array first and then insert this in front...
    Dim mystring As String, mylen As Long, ub As Long
    ub = UBound(myByte)
    mystring = "A A"
    mylen = Len(mystring)
    ReDim Preserve myByte(0 To ub + mylen)
    CopyMemory ByVal VarPtr(myByte(mylen)), ByVal VarPtr(myByte(0)), ub + 1
    ZeroMemory ByVal VarPtr(myByte(0)), mylen
' insert string
    CopyMemory myByte(0), ByVal mystring, mylen
End Sub

Private Sub report()
    Dim i As Long, msg As String
    For i = 0 To UBound(myByte)
        msg = msg & myByte(i) & ","
    Debug.Print msg
End Sub

JohnnAuthor Commented:
I see your invading my other thread! :) I'm looking into your solution...thanks

I'm a bit confused now. You've just accepted my answer but from your comments it looks like you're responding to ameba's comments.

I don't mind getting a few points but maybe in this case they should have gone to ameba? Or did you genuinely intend to accept my answer?
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

  • 8
  • 6
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now