none
Byte-Array schneller durchsuchen RRS feed

  • Frage

  • Hallo,

    ich habe ein Byte-Array, das ca. 11.000 Bytes enthält. In diesem Byte-Array könnten sich folgende Daten befinden:
    <StartFrame><DataFrame><EndFrame><StartFrame><DataFrame><EndFrame>

    Um also ein weiteres Startframe zu finden, habe ich folgenden Tipp gefunden:

            Dim StartFrame2FoundAt As Integer = -1
            For y As Integer = StartFrame1FoundAt + _StartFrame.Length To OrgByteArray.GetUpperBound(0)
                If OrgByteArray.Skip(y).Take(_StartFrame.Length).SequenceEqual(_StartFrame) Then
                    StartFrame2FoundAt = y
                    Exit For
                End If
            Next

    Aber, die Schleife brauch ewig. Bei Arraygröße von 11.000 können das gut und gerne 4-5 Sekunden sein. Und das geht natürlich gar nicht. 

    Wie kann ich am schnellsten nach der Position des evtl. vorhandenen nächsten Startframe in einem Byte-Array suchen?
    Habt ihr vielleicht eine bessere Idee?

    Vielen Dank im voraus!!!!

    Gruß
    Andy

    Sonntag, 17. Dezember 2017 11:46

Antworten

  • Hi Andy,
    Dein Algorithmus prüft jedes Byte, ob da der gesuchte Inhalt beginnt. Das Ist sehr aufwändig. Besser ist es, die CPU nach dem Index des Inhaltes suchen zu lassen. Das geht praktisch mit einer CPU-Anweisung. VB bietet dazu die Instr-Methode für Zeichenketten. In Byte-Arrays kann man erst einmal das Start-Byte suchen und nur bei Erfolg die weiteren Bytes prüfen.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert AndreasMahub Sonntag, 17. Dezember 2017 14:02
    Sonntag, 17. Dezember 2017 12:03

Alle Antworten

  • Hi Andy,
    Dein Algorithmus prüft jedes Byte, ob da der gesuchte Inhalt beginnt. Das Ist sehr aufwändig. Besser ist es, die CPU nach dem Index des Inhaltes suchen zu lassen. Das geht praktisch mit einer CPU-Anweisung. VB bietet dazu die Instr-Methode für Zeichenketten. In Byte-Arrays kann man erst einmal das Start-Byte suchen und nur bei Erfolg die weiteren Bytes prüfen.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert AndreasMahub Sonntag, 17. Dezember 2017 14:02
    Sonntag, 17. Dezember 2017 12:03
  • Hallo Peter,

    Wahnsinn!!!

    Ich hätte niemals gedacht, dass Instr so ein irres Tempo hat! Und ick Idiot nehme eine Schleife :-D

    So funktioniert es wunderbar:

        Public Function FindArrayInArray(ByteArray As Byte(), ArrayToFind As Byte()) As Integer
    
            Return InStr(System.Text.ASCIIEncoding.ASCII.GetString(ByteArray), System.Text.ASCIIEncoding.ASCII.GetString(ArrayToFind), CompareMethod.Binary)
    
        End Function
    

    Und das ist das Ergebnis:

    0 Millisekunden bzw. 2344 Ticks. Meine Schleife da oben brauchte bei einem 5tel der Datenmenge 4-5 SEKUNDEN.

    Danke für den Tipp mit Instr :-)

    Gruß
    Andy

    Sonntag, 17. Dezember 2017 14:07
  • Falls es jemand gebrauchen könnte, hab die Funktion noch um einen optinalen StartIndex erweitert.

        Public Function FindArrayInArray(ByteArray As Byte(), ArrayToFind As Byte(), Optional StartIndex As Integer = 0) As Integer
    
            If StartIndex Then
                ' Da erst ab einer bestimmten Position gesucht werden soll,
                ' schneiden wir das Byte-Array ab.
                ByteArray = ByteArray.Skip(StartIndex).ToArray
            End If
            Return StartIndex + InStr(System.Text.ASCIIEncoding.ASCII.GetString(ByteArray), System.Text.ASCIIEncoding.ASCII.GetString(ArrayToFind), CompareMethod.Binary)
    
        End Function
    

    Wenn man z.B. als Startindex 33333 übergibt, dann dauert es allerdings schon 2ms. Aber immer noch besser als mehrere Sekunden.

    Gruß
    Andy

    Sonntag, 17. Dezember 2017 14:17