![]() |
In Binärdatei suchen
Hallo!
Ich suche nach einer Möglichkeit wie ich in einer Binärdatei nach bestimmten Inhalten suchen kann. Die Suche sollte natürlich möglichst effizent sein. Die Binärdatei wird mit einem TFileStream geöffent. Nun bräuchte ich eine Funktion die ein bestimmtes Bytemuster sucht, also z.B. Seek(myStream, 0x112233), und mir dann das Offset der Fundstelle mitteil... (Ich weiß, dass Seek nicht zum Suchen benutzt wird). Gibt es solche eine Funktion oder muss man sich das selber basteln? Besten Dank Ares |
Re: In Binärdatei suchen
Hallo,
für den Suchvorgang musst du die Daten vom externen Speicher in den Hauptspeicher laden - es führt kein Weg daran vorbei. Wie du dann weiter suchst ist eine Frage der Komplexität deiner Suche: einfaches oder reguläres Suchmuster? Pos() und Regex() helfen dir da weiter. Grüße vom marabu |
Re: In Binärdatei suchen
Pos und Regex finktionieren doch aber nur mit Strings, oder?
==> Daten in TFileStream laden und Byteweise vergleichen... mfg Chtistian |
Re: In Binärdatei suchen
Hallo Christian,
sowohl das Suchmuster, als auch der Datenstrom, lassen sich in Delphi als String betrachten. Das erspart die Implementierung einer speziellen Funktion, die lediglich die Signatur der Funktion Pos() anpassen würde - intern werden schon die vom Prozessor angebotenen Instruktionen für das register-gesteuerte Suchen eines Byte-/Wort-Wertes verwendet. Freundliche Grüße |
Re: In Binärdatei suchen
Es geht um teilweise sehr große Dateien in denen ich nach bestimmte (festen) Bytemustern suchen muss. Die Muster markieren Stellen an denen bestimmte Informationen zu finden sind. Die Muster sind immer gleich, reguläre Ausdrücke sind also nicht notwendig.
Zitat:
Zitat:
Gibt es hierfür bereits Funktionen die das können? Weiß jemand welche Algorithmen pos() verwendet? Ist das effizient? Gruß Ares |
Re: In Binärdatei suchen
Zitat:
|
Re: In Binärdatei suchen
@Marabu:
So weit so klar, aber gibt das nicht Probleme mit #0? Oder is die CompilerMagic da wieder so schlau, dass die sich nicht dran stört? Ich meine mich dran erinner zu können, dass ich mal Probleme mit #0 hatte. Kann aber sein, dass das intern mit PChars zu tun hatte, und die kommen ja mit Sicherheit nicht (ohne weiteres) mit #0 im String klar... @Ares: Zitat:
Zitat:
Zitat:
//Edit: grad gemerkt, dass es noch gar keine 325Bit-Systeme gibt... :mrgreen: mfg Christian |
Re: In Binärdatei suchen
@ Christian,
der Vollständigkeitshalber :roll: Zitat:
Das hebt die Beschränkung zumindest schonmal von 2 GB auf 3 GB, aber somit nur noch 1 GB für das OS. Manchmal kann das hilfreich sein... |
Re: In Binärdatei suchen
Öhm, ich stehe gerade etwas auf dem Schlauch. Wie kann ich den Streaminhalt in einen String einlesen?
Mein erster Versuch tut es jedenfalls schon mal nicht :-|
Delphi-Quellcode:
stream := TFileStream.Create('MeineDatei.bin', fmOpenRead);
stream.Read(test, 25); showMessage(test); |
Re: In Binärdatei suchen
Die Funktion Pos() selbst wird durch einen null character im String nicht behindert:
Delphi-Quellcode:
Ich sage ja auch nicht, dass hier eine Stringverarbeitung vorliegt, sondern dass man durch geschicktes Agieren bestehende Funktionalität für lau nutzen kann.
var
s: String; i: Integer; begin s := '01234'#0'56789'; ShowMessage(IntToStr(Pos('6', s))); // liefert 8 end; Pos() implementiert den brute force Ansatz, wenn ich richtig informiert bin. Was die Suchalgorithmen angeht, so hängt sehr viel von der Länge des (einfachen) Suchmusters (synonym für substring) ab. Für kleine Zeichenketten bis zur Länge drei ist der brute force Algorithmus optimal, für größere hat sich in der Fachwelt bis dato (1994) Boyer-Moore-Horspool durchgesetzt. Die Aussage "das Prinzip ist immer das gleiche" ist so alleine nicht richtig. Komplexe Suchverfahren bedienen sich bei ihren elementaren Schritten natürlich auch des Byte-Vergleichs, aber anstelle des simplen loop-and-compare werden da für den Laien erstaunliche Eigenschaften des Suchstrings analysiert und nutzbar gemacht. Das Buch String Searching Algorithms von Graham A. Stephen vermittelt einen recht guten und kompakten Überblick über die Materie. Freundliche Grüße Einlesen in einen String-Buffer:
Delphi-Quellcode:
Getippt und nicht getestet
const
BUFSIZE = 64 shl 10; var buffer: String; s: Stream; chunk: Integer; begin // ... chunk := Max(BUFSIZE, s.Size - s.Position); if chunk < Length(buffer) then SetLength(buffer, chunk) else SetLength(buffer, BUFSIZE); s.Read(s[1], chunk); // ... end; |
Re: In Binärdatei suchen
Hallo!
Vielen Dank für das Beispiel! Ich habe es so abgeändert: Zitat:
Ich habe folgende beobachtung gemacht: Wenn ich das Programm so laufen lasse, werde mir mit showMessage wunderbar die ersten 10 Byte angezeigt (E0 32 98 00 00 00 00 00 00 00). Aber: Es sind die falschen! Wenn ich mir die Datei mit einem Hex-Editor anschaue kommt diese Bytefolge nirgendwo vor, besonders nicht am Dateianfang. Wenn "stream.Read(buffer[1], chunk);" durch "stream.Read(buffer[1], ZAHL);" ersetze und mit verschiedenen Werten für ZAHL rumprobiere bekomme ich das Ergebnis: ZAHL = 1 bis 84068 --> Es werden die korrekten Bytes angezeigt (D2 18 B4...) ZAHL = 84068 bis 84072 --> Es kommt zu einer Exception ZAHL = 84073 oder größer --> Das falsche Ergebnis wird angezeigt. Das Ergebnis kann ich nicht wirklich deuten? Wie kommen die Zahlen zustande? Wo könnte der Fehler liegen? Besten Dank! Ares |
Re: In Binärdatei suchen
Hallo,
wenn deine Dateien doch riesig groß sind, dann möchtest du sie sicher portionsweise verarbeiten - chunk (maximal 64KB) ist die Portionsgröße und mein Code gehört in eine Schleife. Solange mindestens 64KB Restdaten gelesen werden können, wird der einmal allozierte Buffer benutzt, fällt der Rest unterhalb diese Größe, dann wird der Buffer redimensioniert. Deine Experimente kann ich anhand deiner Angaben nicht so gut kommentieren, da müsstest du wirklich den richtigen Code zeigen. Ist allerdings der Buffer nach wie 64KB groß und du liest deutlich größere Mengen ein, dann überschreibst du angrenzende Speicherbereiche und das Ergebnis muss dich nicht wundern. Freundliche Grüße |
Re: In Binärdatei suchen
Hallo Ares,
versuche es mal mit dieser Änderung:
Delphi-Quellcode:
Ein kleiner Fehler, der aber sehr schnell passiert. Man möchte eine maximale Puffergröße angeben, muß aber dazu die Funktion Min() benutzen. Die Fallunterscheidung habe ich entfernt - sie wird meiner Meinung nach nicht mehr benötigt.
// chunk := Max(BUFSIZE, s.Size - s.Position);
chunk := Min(BUFSIZE, s.Size - s.Position); // Min() statt Max() SetLength(buffer, chunk); s.Read(buffer[1], chunk); Noch ein Hinweis: wenn der Suchstring mehrere Bytes enthält, befindet er sich eventuell nur zum Teil in einem Puffer und wird dann im nächsten fortgesetzt. Diesen Sonderfall mußt du bei der Untersuchung des Pufferinhalts berücksichtigen. Wie man so etwas prinzipiell angehen kann, findest du in ![]() Gruß Hawkeye |
Re: In Binärdatei suchen
Hallo Hawkeye,
danke für die Korrektur - ich ahnte, dass mein disclaimer nötig war ... Freundliche Grüße |
Re: In Binärdatei suchen
Moin Jürgen,
als Vervollständigung der Vervollständigung ;-) Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz