Finden, Ersten Bestimmten Byte in ein Byte[] Array in c#
Ich habe ein byte-array und wünschen zu finden, das erste auftreten (wenn überhaupt) von einem bestimmten byte.
Könnt Ihr mir helfen mit eine schöne, elegante und effiziente Art und Weise, es zu tun?
///Summary
///Finds the first occurance of a specific byte in a byte array.
///If not found, returns -1.
public int GetFirstOccurance(byte byteToFind, byte[] byteArray)
{
}
InformationsquelleAutor divinci | 2009-06-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es wird -1 zurück wenn nicht gefunden
Oder als Sam wies darauf hin, eine Erweiterung-Methode:
- Oder um es generic:
Dann kann man nur sagen:
Ich wollte sagen, Erweiterung Methode, natürlich.
In der Tat. Verändert es...
extension-Methode auch, aber nur in C# 3.0
Was ist der Punkt, erstellen einen wrapper für ein standard-Bibliothek-Funktion? Dies macht nur der code schwieriger zu Lesen, da Sie, um sich die definition der benutzerdefinierten Funktion. Insbesondere eine sinnlose wrapper wie diese riecht etwas unerwartetes versteckt.
InformationsquelleAutor Philippe Leybaert
Array.IndexOf?
InformationsquelleAutor Greg Beech
Da Sie erwähnt Effizienz, hier ist einige stark optimierten C# - code ich geschrieben habe, das verwendet native Adressierung und maximale qword ausgerichtet Lesen, um die Zahl der Speicherzugriffe durch einen Faktor von 8. Ich wäre überrascht, wenn es einen schnelleren Weg, um scan für ein byte im Speicher in .NET.
Dieser gibt die index des ersten Auftretens von byte 'v' innerhalb der Speicherbereich, beginnend bei offset
i
(relativ zur Adressesrc
), aus-und Weiterbildung für die Längec
. Gibt -1 wenn bytev
nicht gefunden.Nicht alarmiert werden, durch die eine Vermehrung, die Sie sehen; es wird nur ausgeführt, maximal einmal pro Aufruf der Funktion, um zu tun, eine endgültige deBruijn-lookup. Der nur-lese-lookup-Tabelle verwendet, die eine einfache gemeinsame Liste von 64-byte-Werte, das erfordert nur einmalig Initialisierung:
Den
-1
Werte sind nie zugegriffen, und können Sie auf null, falls gewünscht, anstatt, wie in der folgenden alternative zu der vorstehenden Tabelle Initialisierungs-code, wenn Sie es vorziehen:Vollständigkeit halber, hier ist, wie man die Funktion mit dem Prototyp-Methode zur Verfügung gestellt, die durch die OP in der ursprünglichen Frage.
Diskussion
Mein code ist ein wenig kompliziert, so dass eine detaillierte Untersuchung ist Links als übung für den interessierten Leser. Sie können studieren ein anderes nehmen auf den Allgemeinen Ansatz des Bande-wise memory-Suche im .NET interne Methode Puffer.IndexOfByte, aber code hat signifikante Nachteile im Vergleich zu mir:
t1 != 0
check gibt eine false positive, und die vier Prüfungen, die Folgen verschwendet. Beachten Sie Ihren "fall-through" - Fall: aufgrund dieser falsch-positiven, die Sie benötigen, vier abschließenden Prüfungen--wodurch fallen-durch-zu pflegen, Korrektheit, statt nur drei.0x7efefeff
oder0x81010100
) und den gelegentlichen "Links-weisen Ausstieg" (d.h., Verlust von Informationen in Bezug auf das most significant byte, das ist das wirkliche problem hier. Im Gegensatz dazu benutze ich ein Unterlauf Berechnung, die dafür sorgt, jedem byte die Berechnung unabhängig von seinen Nachbarn. Meine Methode gibt ein schlüssiges Ergebnis ist in allen Fällen mit keine falsch-positiven oder "fall-through" - Verarbeitung.if-else
Strukturen, da letztere stören können CPU predictive caching. Dieses Problem ist wichtiger für meine 8-byte-scanner, da ohne mithilfe von lookup-ich hätte doppelt so vieleif-else
Bedingungen in der Endkontrolle, als im Vergleich zu einem 4-byte-gang-klug-scanner.Natürlich, wenn Sie nicht damit beschäftigt, alle diese Kleinigkeiten, Sie können einfach kopieren und den code; ich habe Gerät getestet, es ganz ausführlich und verifiziert das richtige Verhalten für alle gut gebildet Eingänge. So, während die Kern-Funktionalität ist bereit zu verwenden, werden Sie wahrscheinlich wollen, fügen Sie eine überprüfung der Argumente.
[edit:]
Wegen der oben beschriebenen Methode gearbeitet hat, so erfolgreich in meine Projekte, die ich erweitert auf 16-bit-Suche. Hier ist der gleiche code angepasst, um die Suche nach einem 16-bit short, ushort, oder char primitive anstelle von
byte
. Mit dieser angepassten Methode auch unabhängig geprüft gegen Ihre jeweiligen unit-test-Methodik angepasst von oben.Und unten sind die verschiedenen überladungen für den Zugriff auf diese für die restlichen 16-bit-primitive, plus
String
(Letzte Abbildung):Beachten Sie, dass die
String
überlastung ist nicht ausdrücklich als eine Erweiterung Methode, da diese höher-performance-Ersatz-version würde die Funktion nie aufgerufen werden, die Art und Weise (built-in Methoden mit dem gleichen Namen immer Vorrang vor der Erweiterung Methoden). Verwenden Sie als Erweiterung aufString
Instanzen, Sie können ändern Sie den Namen dieser Methode. Als BeispielIndexOf__(this String s,...)
würde ihn erscheinen neben den built-in method name in Intellisense Inserate, vielleicht eine hilfreiche Erinnerung zu opt-in. Ansonsten, wenn Sie nicht brauchen, Erweiterung der syntax, Sie können nur sicherstellen, dass Sie rufen Sie diese optimierte version direkt wie eine statische Methode der eigenen Klasse, wenn Sie es verwenden möchten, anstatts.IndexOf(Char ch)
.InformationsquelleAutor Glenn Slayden