Results 1 to 21 of 21

Thread: [RESOLVED] Copy Array Bytes by Block to Variant Arrays

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Resolved [RESOLVED] Copy Array Bytes by Block to Variant Arrays

    I'm trying to read in as fast as possible a binary file and put it into a Variant Array by what I call Blocks (groups). The header for each block is a vbBack.

    I read in the Binary File into a Byte Array using procedure: "Bin_ReadAll" This read works but seems slow -- about 17 seconds for 110,000 bytes. (Note: 17 seconds is with routine (not posted)
    verifying bytes. Actual time to Load is < 1 second.

    I then try and copy the bytes into the Variant Array using the procedure: "SplitBytesToBlocks".

    ===============================
    IGNORE CODE in Post #1, See Post #2 for Rework.
    Realized I had not posted the actual Type and the correct dimension for
    the dest array in CopyMemory. However, when trying to verify get
    error "type mismatch". See end of procedure: "SplitBytesToBlocks".
    for verify.
    ===================================

    Code:
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
    
    Public Function Bin_ReadAll(strPath As String, arrBytes() As Byte)
    'Reads Entire File in One Line of Code to a Byte Array (base 1)
    'THIS WORKS
    
    Dim file_name As String
    Dim file_length As Long
    Dim fnum As Integer
    
        file_name = strPath
        file_length = FileLen(file_name)
    
        fnum = FreeFile
        ReDim arrBytes(1 To file_length)
    
        Open file_name For Binary As #fnum
        Get #fnum, 1, arrBytes
        Close fnum
        
        
        '=========================
    
    'Dim txt As String
    'Dim i As Long
    '
    '    ' Display the results.
    '    For i = 1 To UBound(arrBytes)                      ' file_length
    '        txt = txt & Format$(arrBytes(i)) & vbCrLf
    '    Next i
       
        
    End Function
    
    
    Public Sub SplitBytesToBlocks(arrBytes() As Byte, arrOut() As Variant, Delimiter As Byte)
    
        Dim i As Long
        Dim j As Long                 ''Dimension Counter for arrOut
        Dim blnFound As Boolean
        Dim byteStart As Long
        Dim LenBlock As Long
        Dim tmp(29) As Variant
        
        j = -1
        For i = LBound(arrBytes) To UBound(arrBytes)
        
            If arrBytes(i) = Delimiter Then
            
                'Skip the 1st byte as a Block
                If Not i = LBound(arrBytes) Then
                  LenBlock = (i - byteStart) + 1
                  
                  j = j + 1
                  Call CopyMemory(tmp(j), arrBytes(byteStart), LenB(LenBlock))
    
                End If
            
                'Set Flag
     'not needed           blnFound = True
                
                byteStart = i
                
                 'Turn Off Flag
     'not needed           blnFound = False
                
            End If
        
        Next
        
        'Copy the Last Block
        j = j + 1
        LenBlock = (i - byteStart) + 1
        Call CopyMemory(tmp(j), arrBytes(byteStart), LenB(LenBlock))
         
        '----------------------------
        'Verify tmp has data
        '-----------------------------
        Dim v As Variant
        For i = LBound(tmp) To UBound(tmp)
             v = tmp(i)
        Next
        
    
    End Sub
    Last edited by vb6forever; Jan 23rd, 2018 at 05:46 PM.

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    However, when trying to verify get
    error "type mismatch". See end of procedure: "SplitBytesToBlocks".
    for verify error.

    Code:
    Private Type tmpInfo
        Test() As Variant
    End Type
    
    Private tmp() As tmpInfo
    
    'Note that in order to use this, you must also declare the CopyMemoryMethod like this:
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
    
    Public Function Bin_ReadAll(strPath As String, arrBytes() As Byte)
    'Reads Entire File in One Line of Code to a Byte Array (base 1)
    'THIS WORKS
    
    Dim file_name As String
    Dim file_length As Long
    Dim fnum As Integer
    
        file_name = strPath
        file_length = FileLen(file_name)
    
        fnum = FreeFile
     '   ReDim arrBytes(1 To file_length)
        ReDim arrBytes(1 To file_length)
    
        Open file_name For Binary As #fnum
        Get #fnum, 1, arrBytes
        Close fnum
        
        
        '=========================
    
    'Dim txt As String
    'Dim i As Long
    '
    '    ' Display the results.
    '    For i = 1 To UBound(arrBytes)                      ' file_length
    '        txt = txt & Format$(arrBytes(i)) & vbCrLf
    '    Next i
       
        
    End Function
    
    
    Public Sub SplitBytesToBlocks(arrBytes() As Byte, arrOut() As Variant, Delimiter As Byte)
    
        Dim i As Long
        Dim j As Long                 ''Dimension Counter for arrOut
        Dim blnFound As Boolean
        Dim byteStart As Long
        Dim LenBlock As Long
    '    Dim tmp(29) As Variant
        
        j = -1
        For i = LBound(arrBytes) To UBound(arrBytes)
        
            If arrBytes(i) = Delimiter Then
            
                'Skip the 1st byte as a Block
                If Not i = LBound(arrBytes) Then
                  LenBlock = (i - byteStart) + 1
                  
                  j = j + 1
                  ReDim Preserve tmp(j)
                  ReDim Preserve tmp(j).Test(LenBlock)
                  Call CopyMemory(tmp(j).Test(0), arrBytes(byteStart), LenB(LenBlock))
    
                End If
            
                byteStart = i
               
            End If
        
        Next
        
        'Copy the Last Block
        j = j + 1
        LenBlock = (i - byteStart) + 1
        ReDim Preserve tmp(j)
        ReDim Preserve tmp(j).Test(LenBlock)
        Call CopyMemory(tmp(j).Test(0), arrBytes(byteStart), LenB(LenBlock))
         
        '----------------------------
        'Verify tmp has data
        '-----------------------------
        Dim v As Variant
        For i = LBound(tmp) To UBound(tmp)
        For j = LBound(tmp(i).Test(j)) To UBound(tmp(i).Test(j))  '<<type mismatch
             v = tmp(i).Test(j)
        Next
        Next
    
    End Sub
    Last edited by vb6forever; Jan 23rd, 2018 at 05:48 PM.

  3. #3
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,940

    Re: Copy Array Bytes by Block to Variant Arrays

    Don't you need to leave off the (j) for your LBound and UBound?

    I didn't really study things, but that doesn't look right.

    EDIT1: Something like this...

    Code:
    
    For j = LBound(tmp(i).Test) To UBound(tmp(i).Test)
    
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    Thanks Elroy was just overlooking it. That resolves the "type mismatch"

    Looks like I'm getting the correct dimension of tmp(i).Test(j) based on LenBlock copied,
    but no data -- just Empty.
    Never tried using CopyMemory to in effect cast from Byte to some other data type (here Variant).
    Do you know if this is in fact can be done?

  5. #5
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,940

    Re: Copy Array Bytes by Block to Variant Arrays

    Hmmm, I didn't look at that part, but casting into a variant can be tricky. Variants often don't actually contain the data, but rather have a pointer to it. That's always the case with arrays. Therefore, you'll need to do some de-referencing to do that. Also, since it's an array, you may also need to wade through the SafeArray structure.

    Just an honest question. Why not just put the array in the variant (simple LET)?

    EDIT1: I did start looking at your code a bit, but I'm out of time. I'm sure someone else will come along and study your CopyMemory calls. Good Luck.
    Last edited by Elroy; Jan 23rd, 2018 at 08:06 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    Just an honest question. Why not just put the array in the variant (simple LET)?
    Unless I'm missing something -- most probable -- how are you going to Let various portions (I call blocks)
    of the Byte Array to a Variant Array ?
    I can see where the entire Array can be LET, but if I do that, I'm in the same box as the byte array.
    That is having to Loop the variant array in order to ID (cutout) each Block (group).
    Similar to extracting strings from within a string.

  7. #7
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,068

    Re: Copy Array Bytes by Block to Variant Arrays

    [...]
    Last edited by dz32; Apr 26th, 2019 at 11:25 AM.

  8. #8
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,906

    Re: Copy Array Bytes by Block to Variant Arrays

    Can you explain what you want to accomplish?
    Do you want an array of an array of bytes?
    Something like the Split() function on a string?

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    =====
    dz32.
    =====
    It would be interesting if you can copymemory to a variant array
    That's what I thought, but never actually seen implementation.
    Obviously MS is doing something with their Conversion (CByte, CStr, etc). to get something
    similar happen.

    use vbscript regular expressions library
    Prefer stay away from vbscript implementation.

    Read file in chunks
    Would then have to search within each chunk for the header (vbback) and then split and join
    chunks such that each block out begins with vbback.

    ===========
    Arnoutdb
    ===========



    Can you explain what you want to accomplish?
    Read a byte file, split it into blocks (chunks), and save "each block" in a separate variant array.
    Each Block Out must have a header delimiter of vbback.
    i
    Do you want an array of an array of bytes?
    Not as final output. Must be variant arrays.

    Something like the Split() function on a string?
    Yes, but instead of a trailer such as splitting on vbCrLf, need to split on the header of vbback.
    Last edited by vb6forever; Jan 24th, 2018 at 05:51 AM.

  10. #10
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,048

    Re: Copy Array Bytes by Block to Variant Arrays

    Hi,

    I use this to copy...

    Code:
    Private Function CopyFile(QuellFile As String, ZielFile As String) As Boolean
    
       Dim QF As Integer
       Dim ZF As Integer
       Dim Percent As Double
       Dim CopyLen As Double
       Dim Copied As Double
       Dim AnzByte As Long
       Dim Msg As String
       Dim s As String
       
          'Block to Copy
          AnzByte = 256& * 256&
          
          On Error GoTo Fehler
          QF = FreeFile
          Msg = "Fehler beim Öffnen QuellFile"
          Open QuellFile For Binary As #QF
          CopyLen = LOF(QF)
          
          
          ZF = FreeFile
          Msg = "Fehler beim Öffnen ZielFile"
          Open ZielFile For Output As #ZF
          
          On Error GoTo 0
          
          Do
             If CopyLen = Copied Then
                Exit Do
             ElseIf (CopyLen - Copied) < AnzByte Then
                AnzByte = CopyLen - Copied
             End If
             s = Space(AnzByte)
             Get #QF, Copied + 1, s
             Print #ZF, s;
             Copied = Copied + AnzByte
             
             Picture1.Visible = True
             Percent = (Copied * 100) \ CopyLen
             ShowPercent Picture1, Percent
             DoEvents
          Loop
          
          Close #QF, #ZF
          CopyFile = True
          Picture1.Visible = False
          Exit Function
          
    Fehler:
          If ZF > 0 Then
             Close #QF
          End If
          Msg = Msg & vbCrLf & vbCrLf & "Fehler: " & _
                Err.Number & vbCrLf & Err.Description
          MsgBox Msg, vbCritical, "Fehler Copy"
          Err.Clear
    End Function
    HTH

    regards
    Chris
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  11. #11
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,906

    Re: Copy Array Bytes by Block to Variant Arrays

    Read a byte file, split it into blocks (chunks), and save "each block" in a separate variant array.
    Why a variant array?

    Can you explain what you are going to do with your array of variant arrays?

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    ====
    ChisE
    ====
    Thanks for post. Will take a look see, but cursory review looks like just copy one to other not separating by blocks.

    =====
    Arnoutdv
    =======
    Why a variant array?
    Can you explain what you are going to do with your array of variant arrays?
    The receiving procedure requires a Type with various array elements being variant.

    FWIW: I'm trouble shooting an email program which receives email using Winsock.
    It is failing in the parsing procedure on selected emails.
    I've obtained a group of emails (byte array), some of which are failing, and now what to fed them
    into the parsing routine to troubleshoot. Consequently, wish to separate those that work
    from those that don't to narrow down where parsing error is occurring.
    This is being done offline.

  13. #13
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Copy Array Bytes by Block to Variant Arrays

    If the issue is reading a file of BLOBs each having a BS (&H08) byte as a prefix and placing these into a Variant array as Byte arrays with the BS stripped off... I don't see the issue.

    I must have missed something, because it seems like a common enough sort of thing. Chunk the data in, parse for the BLOB data.


    Here I have created BLOBs of varying size that begin with a 6 byte Index prefix (ANSI digits with left-zero fill), then an ANSI space, then some varying length ANSI text.

    Name:  sshot1.png
Views: 992
Size:  1.4 KB


    After a reboot to clear the disk cache (and thus get more accurate timing), this program reads the data, parses it, stores the BLOBs without the "header" BS byte in a Variant array. Then the "verify" step grabs and displays the Index prefix of the first and last BLOB loaded.

    Name:  sshot2.png
Views: 1083
Size:  2.3 KB


    Code:
    Option Explicit
    
    Private Declare Function GetTickCount Lib "kernel32" () As Long
    
    Private Blobs() As Variant
    
    Private Sub Command1_Click()
        Const CHUNKSIZE As Long = 100 'ReDim Preserve chunk size.
        Dim T0 As Long
        Dim Delim As String
        Dim F As Integer
        Dim BytesLeft As Long
        Dim Buffer() As Byte
        Dim BufferString As String
        Dim PastFirstBlob As Boolean
        Dim BufferStringCursor As Long
        Dim BlobString As String
        Dim DelimPos As Long
        Dim Blob() As Byte
        Dim BlobsIndex As Long
    
        T0 = GetTickCount()
        Delim = ChrB$(vbKeyBack)
        ReDim Blobs(CHUNKSIZE - 1)
        F = FreeFile(0)
        Open "data.dat" For Binary Access Read As #F
        BytesLeft = LOF(F)
        ReDim Buffer(32767)
        Do While BytesLeft > 0
            If BytesLeft < UBound(Buffer) + 1 Then ReDim Buffer(BytesLeft - 1)
            Get #F, , Buffer
            BufferString = Buffer
            BytesLeft = BytesLeft - (UBound(Buffer) + 1)
            'Base 1 for use with String operations:
            If PastFirstBlob Then
                BufferStringCursor = 1
            Else
                PastFirstBlob = True
                BufferStringCursor = 2
            End If
            Do While BufferStringCursor < LenB(BufferString)
                DelimPos = InStrB(BufferStringCursor, BufferString, Delim, vbBinaryCompare)
                If DelimPos > 0 Then
                    BlobString = BlobString _
                               & MidB$(BufferString, _
                                       BufferStringCursor, _
                                       DelimPos - BufferStringCursor)
                    Blob = BlobString
                    BlobString = vbNullString
                    If BlobsIndex > UBound(Blobs) Then
                        ReDim Preserve Blobs(UBound(Blobs) + CHUNKSIZE)
                    End If
                    Blobs(BlobsIndex) = Blob
                    Erase Blob
                    BlobsIndex = BlobsIndex + 1
                    BufferStringCursor = DelimPos + 1
                Else
                    BlobString = BlobString & MidB$(BufferString, BufferStringCursor)
                    Exit Do
                End If
            Loop
        Loop
        Close #F
        'Last Blob:
        Blob = BlobString
        BlobString = vbNullString
        If BlobsIndex > UBound(Blobs) Then
            ReDim Preserve Blobs(UBound(Blobs) + CHUNKSIZE)
        End If
        Blobs(BlobsIndex) = Blob
        Erase Blob
        If (BlobsIndex + 1) Mod CHUNKSIZE <> 0 Then ReDim Preserve Blobs(BlobsIndex)
    
        Label1.Caption = "Blobs(0 To " _
                       & CStr(BlobsIndex) _
                       & ") loaded in " _
                       & Format$(CSng(GetTickCount() - T0) / 1000, "0.0##") _
                       & " sec"
        Command2.Enabled = True
    End Sub
    
    Private Sub Command2_Click()
        Label3.Caption = StrConv(LeftB$(Blobs(0), 6), vbUnicode)
        Label4.Caption = "Blobs(" & CStr(UBound(Blobs)) & ")"
        Label5.Caption = StrConv(LeftB$(Blobs(UBound(Blobs)), 6), vbUnicode)
    End Sub
    Both programs attached.


    Seems easy enough, and fast enough for most purposes. What am I missing?
    Attached Files Attached Files

  14. #14

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    Thanks dilettante: Will take a look see.
    BTW - haven't forgotten about JasonBag, just pushed aside for now do to time constraints.

    Also question for my edification:
    Do you know whether CopyMemory can be used to Type Cast as in post #2 -- or some alternate CopyMemory rework?
    Last edited by vb6forever; Jan 24th, 2018 at 12:40 PM.

  15. #15
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Copy Array Bytes by Block to Variant Arrays

    Quote Originally Posted by vb6forever View Post
    Do you know whether CopyMemory can be used to Type Cast as in post #2 -- or some alternate CopyMemory rework?
    I can't really figure out what you were trying to do in post #2.

    I thought you said you wanted a Variant array containing Byte arrays, but what you have there is some weirdness with an array of UDTs that contain a Variant array. Why would you want each BLOB to have the overhead of a UDT plus each Byte of each BLOB having the overhead of a Variant? You are throwing away memory like a drunken sailor.

    If you can clarify what you are after maybe we can be more helpful. I think I'm lost.

  16. #16

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    I can't really figure out what you were trying to do in post #2.
    Interesting. I thought it was fairly straightforward.
    I'm just trying to take a byte array, split it based on a header byte (vbback in this case is the header byte for each grouping),
    then move each byte group (chunk, segment or blob depending on ones terminology) into a Structure element, where that element happens to be a Variant array.

    Each byte array group WITHIN the byte array varies in length, hence one must locate (id) the header byte at the start of the group when reading in order to know where each group begins.

    A structure is being used because each byte group can be further subdivided into two parts.

    Right now I'm just trying to solve the splitting of each group, as the splitting of the subgroups will duplicate the group split.

    Hope that's clear.

  17. #17
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: Copy Array Bytes by Block to Variant Arrays

    Quote Originally Posted by vb6forever View Post
    I thought it was fairly straightforward.
    The problem probably is - though your code isn't (I'm also quite confused by it)...

    Quote Originally Posted by vb6forever View Post
    A structure is being used because each byte group can be further subdivided into two parts.

    Right now I'm just trying to solve the splitting of each group, as the splitting of the subgroups will duplicate the group split.
    Why not solve everything in one go then ...
    (the UDT-def below already addressing your "two parts" with a matching type - no Variant in sight anywhere - and also no CopyMemory):
    Code:
    Option Explicit
     
    Private Type twoParts
        Part1() As Byte
        Part2() As Byte
    End Type
    
    Private Sub Form_Load()
      Dim B() As Byte, List() As twoParts, i As Long
          B = StrConv(vbBack & "a1" & vbTab & "b1" & vbBack & "a2" & vbTab & "b2", vbFromUnicode)
     
      For i = 0 To SplitBytes(B, List, vbKeyBack, vbKeyTab) - 1
        With List(i)
          Debug.Print StrConv(.Part1, vbUnicode), StrConv(.Part2, vbUnicode)
        End With
      Next
    End Sub
     
    Private Function SplitBytes(B() As Byte, List() As twoParts, ByVal BlobDel As Byte, ByVal PartDel As Byte) As Long
      Dim i As Long, BlobIdx As Long, PartIdx As Long, PartLen As Long
      
      ReDim Preserve B(0 To UBound(B) + 1): B(UBound(B)) = BlobDel
      Do Until B(i) = BlobDel: i = i + 1: Loop
      
      For i = i + 1 To UBound(B)
        If B(i) = PartDel Or B(i) = BlobDel Then
          ReDim Preserve List(0 To BlobIdx)
          If PartIdx = 0 Then List(BlobIdx).Part1 = MidB$(B, i - PartLen + 1, PartLen)
          If PartIdx = 1 Then List(BlobIdx).Part2 = MidB$(B, i - PartLen + 1, PartLen)
          PartLen = 0
          If B(i) = BlobDel Then BlobIdx = BlobIdx + 1: PartIdx = 0 Else PartIdx = PartIdx + 1
        Else
          PartLen = PartLen + 1 'increment PartLen
        End If
      Next
      SplitBytes = BlobIdx
    End Function
    BTW, how's your JSON-parsing coming along...

    Olaf

  18. #18

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    Olaf : Thanks for feedback.

    (I'm also quite confused by it)...
    Even more interesting.

    In regard to the code.
    I have a byte file with over 100,000 bytes.
    There are 28 groupings within this file.
    # bytes in each group vary.
    For example :

    <--- Group 1 ---><---Group 2----><---- Group 3---><............. ><-- Group 28 --->
    vbBack 01 03 25 vbback 10 35 85 vbback 86 100 18 vbback .................................. EOF

    Each grouping starts with a header byte of vbback (the delimiter).
    I loop the file one byte at a time, tracking each byte position as it is read -- using the loop counter.
    When the delimiter (first byte in each group AKA vbback AKA header byte) is encountered, its
    position value is assigned to a variable called byteStart.
    The ending byte of each group is then calculated using the formula: LenBlock = (i - byteStart) + 1
    After that calculation is when I attempt to use CopyMemory to copy "each" byte group to the Structure variant array.
    The loop continues doing the same thing till EOF, using CopyMemory and each groups Start position and the Length (# bytes in each group) in an attempt to copy each byte group to the Structure variant array.

    The kicker in this is whether or Not one can use CopyMemory to copy a byte array to a variant array.
    No error occurs, but no bytes appear to be copied.

    I'm sorry I mentioned the subgroups as this only confused the issue.


    BTW, how's your JSON-parsing coming along...
    Per post #14 is back burner for now since 1 off.
    Last edited by vb6forever; Jan 24th, 2018 at 09:58 PM.

  19. #19
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: Copy Array Bytes by Block to Variant Arrays

    Quote Originally Posted by vb6forever View Post
    <--- Group 1 ---><---Group 2----><---- Group 3---><............. ><-- Group 28 --->
    vbBack 01 03 25 vbback 10 35 85 vbback 86 100 18 vbback .................................. EOF

    Each grouping starts with a header byte of vbback (the delimiter).
    As said your format - and the "parsing-stuff" are understood and not really the problem.

    The problem I have with your code is the data-structures you use for (temp) storage -
    and the lines which finally do that weird copying of Blob-Bytes into a Member of an UDT-Array, which itself is a Variant-Array.

    In my opinion you need only a Single Variant-Array (if we leave the SubParts out for the moment) -
    and no CopyMemory and also no UDT - because the following works, if you'd care to check it out:
    (only thing different in the Input-Data is, that my ByteArray B() is zerobased instead of your onebased-fileread-result.

    Code:
    Private Sub Form_Load()
      Dim B() As Byte, List() As Variant, i As Long
          B = StrConv(vbBack & "a" & vbBack & "b" & vbBack & "c", vbFromUnicode)
          
      For i = 0 To SplitBytes(B, List, vbKeyBack) - 1
        Debug.Print TypeName(List(i)), StrConv(List(i), vbUnicode)
      Next
    End Sub
    
    Private Function SplitBytes(B() As Byte, List(), ByVal BlobDel As Byte) As Long
      Dim i As Long, BlobIdx As Long, BlobLen As Long, Blob() As Byte
      
      ReDim Preserve B(0 To UBound(B) + 1): B(UBound(B)) = BlobDel
      Do Until B(i) = BlobDel: i = i + 1: Loop
      
      For i = i + 1 To UBound(B)
        If B(i) = BlobDel Then
          Blob = MidB$(B, i - BlobLen + 1, BlobLen)
          ReDim Preserve List(0 To BlobIdx): List(BlobIdx) = Blob
          BlobLen = 0: BlobIdx = BlobIdx + 1
        Else
          BlobLen = BlobLen + 1
        End If
      Next
      SplitBytes = BlobIdx
    End Function
    The longer line which does the StrConv in Form_Load actually only constructs an input-array with the following test-content:
    [8, 97, 8, 98, 8, 99]

    And looping over the List-Result prints out 3 found "Blobs", which are of type ByteArray and contain
    the Ascii-Values for a, b, and c respectively (each blob-bytearray consisting of only a single char-value).

    Olaf

  20. #20

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    Olaf:

    Got some output using your code.
    Still need to verify output.
    FWIW had to make a base adjustment by changing line in SplitBytes do "subscript error"

    From: ReDim Preserve B(0 To UBound(B) + 1)
    To: ReDim Preserve B(LBound(B) To UBound(B))

    Will post back after verify.

  21. #21

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: Copy Array Bytes by Block to Variant Arrays

    Let me thank everyone for posting.
    A special thanks to Olaf:
    1) I used his code with some small modifications.
    Of note was that I wanted to keep the header byte with each block (Blob).
    2) I learned something. His approach to add a header byte on the each of the byte array
    was something I've never seen and yet worked well.

    Code as revised with Notes added.

    Code:
    Public Function SplitBytes(arrByte() As Byte, List(), ByVal Delimiter As Byte) As Long
    
      Dim i As Long
      Dim BlobIdx As Long
      Dim BlobLen As Long
      Dim Blob() As Byte
      
      'Increase the Size of the Input Array by one byte
      ReDim Preserve arrByte(LBound(arrByte) To UBound(arrByte) + 1)
     
      'Assign the Delimiter tp this Last byte
      'This is needed so that a delimiter is encountered (like EOF)
      'to allow our For/Next to exit
      arrByte(UBound(arrByte)) = Delimiter
      
      'My Add for My Mental Clarity.
      'Not really needed as System initializes all variables to zero
      BlobIdx = 0
      BlobLen = 0
      
      'Start at the first byte
      i = 1
      
      'Check byte array to get position of 1st delimiter in file
      'May Not always be at start of file
      Do Until arrByte(i) = Delimiter
           i = i + 1
       Loop
    
       'Start Looping one byte beyond our delimiter
       'and loop to UBound. (note: UBound contains a delimiter)
        For i = i + 1 To UBound(arrByte)
        
              If arrByte(i) = Delimiter Then
                 
                 'Delimiter Encountered so move the Block of bytes
                 'From the Delimiter to the byte before the delimiter
                 'to the Blob (temporary) byte array.
                 Blob = MidB$(arrByte, i - BlobLen - 1, BlobLen)
                
                'Increase the Size of the LIst Array to Hold the Next Block
                ReDim Preserve List(0 To BlobIdx)
                
                'Save the Block from Blob (temporary) array to the List array
                List(BlobIdx) = Blob
                
                'Reinitalize counters for next Block Read
                BlobLen = 0
                BlobIdx = BlobIdx + 1
                
              Else
                  'Track the number of bytes read until
                  'a delimiter is encountered
                   BlobLen = BlobLen + 1
              End If
              
        Next
        
        SplitBytes = BlobIdx
      
    End Function

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width