Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi String in 3 MB großen Dateien suchen (https://www.delphipraxis.net/23882-string-3-mb-grossen-dateien-suchen.html)

Uncle Cracker 11. Jun 2004 11:27


String in 3 MB großen Dateien suchen
 
Ich habe jetzt mal eine Frage: Gibt es eine Möglichkeit Strings in Dateien zu suchen die Größer sind als 3 MB (Datei)?

Ich habe zwar schon einiges gefunden, aber da werden nur 1MB der Datei durchsucht :( Gibt es vielleicht eine Methode der die Größe der Datei egal ist?

Vielleicht hat das schonmal jemand gemacht und kann mir helfen.


:love: Danke UC

sakura 11. Jun 2004 11:29

Re: String in 3 MB großen Dateien suchen
 
Zitat:

Zitat von Uncle Cracker
Ich habe zwar schon einiges gefunden, aber da werden nur 1MB der Datei durchsucht

Gib mal ein Beispiel - warum sollte das nicht mit größeren Dateien funktionieren :shock:

...:cat:...

Uncle Cracker 11. Jun 2004 11:39

Re: String in 3 MB großen Dateien suchen
 
Es wird zwar hier nicht nach einem String sondern nach Hexwerten gesucht, ist aber das gleiche (eine Methode von himitsu):

Delphi-Quellcode:
  Const Groesse = 3072000; // 3000 KB ~ 3 MB = 3000 * 1024 = 3072000 Byte

  Var FS: TFileStream;
    Buffer: Array[0..Groesse-1] of Byte;
    I: Integer;
    B: Byte;

  Begin
    Try
      {Datei öffnen}
      FS := TFileStream.Create('C:\Test.exe', fmOpenReadWrite);
      {Daten einlesen}
      FS.Read(Buffer, Groesse);
      {Bytefolge suchen}
      For I := 0 to Groesse - 3 do
        If (Buffer[I] = $78) and
          (Buffer[I + 1] = $78) and
          (Buffer[I + 2] = $78) Then Begin
          Showmessage('Gefunden')
        End;
      FS.Free;
    Except
      On EFOpenError do ShowMessage('Datei konnte nicht geöffnet werden');
      Else ShowMessage('Unbekannter Fehler');
    End;
  End;

Wenn ich das jetzt mache kommt ein Stack-Überlauf, da wahrscheinlich die Größe für den Buffer wahrscheinlich zu groß ist. Aber man muss doch über Buffer suchen oder etwa nicht :roll:
Gibt's da noch eine andere Möglichkeit?

Niko 11. Jun 2004 12:09

Re: String in 3 MB großen Dateien suchen
 
Die einfachste Möglichkeit dürfte es sein, die maximale Stackgröße mit
Delphi-Quellcode:
{$MAXSTACKSIZE 4000000}  // max. Stackgröße etwa 4 MB
entsprechend zu erhöhen.

Uncle Cracker 11. Jun 2004 12:11

Re: String in 3 MB großen Dateien suchen
 
Danke funktioniert, hat das irgendwelche Nachteile bzw. muss ich den Stack dann am Ende wieder "runterschrauben"?

Niko 11. Jun 2004 12:25

Re: String in 3 MB großen Dateien suchen
 
Zitat:

Zitat von Uncle Cracker
hat das irgendwelche Nachteile

Soweit ich weis nicht, aber da sollte vielleicht noch mal jemand schreiben der sich mit Stack, Heap, etc. besser auskennt.
Zitat:

Zitat von Uncle Cracker
muss ich den Stack dann am Ende wieder "runterschrauben"

Nein, die Einstellung besagt nur wieviel Stack-Speicher maximal von deinem Programm benutzt wird, um alles andere kümmert sich weiterhin Delphi.

Basilikum 11. Jun 2004 13:08

Re: String in 3 MB großen Dateien suchen
 
Zitat:

Zitat von Uncle Cracker
Danke funktioniert, hat das irgendwelche Nachteile bzw. muss ich den Stack dann am Ende wieder "runterschrauben"?

die sauberere Lösung wäre, das ganze in den Heap zu verfrachten:

Delphi-Quellcode:
  Var FS: TFileStream;
    {dynamisches Array verwenden}
    Buffer: Array of Byte;
    I: Integer;
    B: Byte;

  Begin
    Try
      {Datei öffnen}
      FS := TFileStream.Create('C:\Test.exe', fmOpenReadWrite);
      {Speicher für Buffer allozieren}
      SetLength(Buffer,FS.Size);
      {Daten einlesen (8ung: Buffer>>[0]<<}
      FS.Read(Buffer[0],Length(Buffer));
      {Bytefolge suchen}
      For I := 0 to Length(Buffer) - 3 do
        If (Buffer[I] = $78) and
          (Buffer[I + 1] = $78) and
          (Buffer[I + 2] = $78) Then Begin
          Showmessage('Gefunden')
        End;
      FS.Free;
    Except
      On EFOpenError do ShowMessage('Datei konnte nicht geöffnet werden');
      Else ShowMessage('Unbekannter Fehler');
    End;
  End;

Uncle Cracker 11. Jun 2004 13:13

Re: String in 3 MB großen Dateien suchen
 
:love: Danke schön funktioniert einwandfrei :thuimb:

Jens Schumann 11. Jun 2004 13:45

Re: String in 3 MB großen Dateien suchen
 
Hallo Uncle Cracker,
ich empfehle Dir den Boyer/Moore Algorithmus
Ich habe dort ein Beispiel-Projekt und die Komponente hinterlegt. Außerdem eine kleine
Powerpoint-Präsentation, die den Algo erklärt.
Die Suche läuft knatter schnell.

Uncle Cracker 11. Jun 2004 14:23

Re: String in 3 MB großen Dateien suchen
 
@JS
Also bei meinem Test mit deiner mitgelieferten Datei stimmte das Ergebnis nicht, dass ich erhalten hatte. Lag vielleicht daran, dass die Datei 2.5 MB groß war.


Noch eine etwas andere Frage die was damit zutun hat, aber ich nicht extra einen neuen Thread aufmachen möchte:

Kann man die die Abfrage nicht eigentlich auch irgendwie einfacher machen also die ganze Zeit immer mit "and" die Werte zuverknüpfen? Vielleicht mit einem Array:

Delphi-Quellcode:
const
  MyArry:array[0..2] of Byte=
 ($78, $78, $78);

Habe das zwar probiert aber das will nicht wirklich, denn die Abfrage mit "Buffer[I] = " bekomme ich irgendwie nicht hin :(

Hätte vielleicht da noch jemand eine Lösung?


:love: Danke UC

Jens Schumann 11. Jun 2004 15:10

Re: String in 3 MB großen Dateien suchen
 
Zitat:

Zitat von Uncle Cracker
Also bei meinem Test mit deiner mitgelieferten Datei stimmte das Ergebnis nicht, dass ich erhalten hatte. Lag vielleicht daran, dass die Datei 2.5 MB groß war.

Wenn Du es sagst mag es wohl stimmen. Vorstellen kann ich mir das aber nicht. Ich habe die Komponente lange getestet und schon einige Zeit im Produktiveinsatz. Bislang sind mir keine Beschwerden zu Ohren gekommen.

Es ganz bestimmt nichts mit der Größe der Datei zu tun.

Kann ich mir Deine Datei irgendwo downloaden. Ich würde sehr gerne mal probieren.
Wie oft muss denn xxx darin vorkommen?

Jens Schumann 11. Jun 2004 17:18

Re: String in 3 MB großen Dateien suchen
 
Moin Uncle Cracker,
Du hast Recht.
Es liegt aber nicht der Größe der Datei, sondern an der Häufigkeit des Wortes. :shock:

Die Datei wird über TFileStream in 4096 Byte Blöcken bearbeitet.
Bevor ein neuer Block eingelesen wird, wird am Ende der Blockverarbeitung
geguckt, ob die aktuelle Stream Position + der Textlänge kleiner ist als
Stream.Size. Ja, wird Stream.Positon von der aktuellen Position um die
Textlänge zurückgesetzt. Dadurch wird verhindert, dass das gesuchte Wort
durch eine Blockgrenze zerschnitten wird. Wenn das gesuchte Wort den Block
abschließt wird es dadurch aber zweimal gezählt. Das müsste der Fehler sein.
Arbeite gerade dran

Jens Schumann 12. Jun 2004 18:54

Re: String in 3 MB großen Dateien suchen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Moin Uncle Cracker,
vielen Dank für Deinen Hinweis. Ich war fest davon überzeugt, dass die Komponente
einwandfrei funktioniert. Ich habe sie nämlich gründlich getestet (Das habe ich gedacht).
Aber wohl nie mit Dateien, die den einen oder anderen Grenzfall enthielten.

Ich habe die Komponente überarbeitet und jetzt verschiedene Grenzfälle
bei den Tests berücksichtigt. Mir ist kein Fehler mehr aufgefallen.

Mit der Komponente habe ich eine 19 MB Testdatei nach der Häufigkeit der
Zeichenkette 'xxx' durchsucht. Das hat unter 1 Sekunde gedauert.

Uncle Cracker 12. Jun 2004 21:55

Re: String in 3 MB großen Dateien suchen
 
Danke das du dir eine solche Mühe machst, werde mal testen.

Könnte man deine Komponente vielleicht noch so ändern, dass nicht nach einem String sondern nach Hexwerten gesucht wird?

CCRDude 13. Apr 2007 08:39

Re: String in 3 MB großen Dateien suchen
 
Glückauf,

Ich hoffe es macht hier nichts, eine derart alte Diskussion auszugraben, aber ich habe gerade eine Anmerkung zu diesem schreibgeschütztem Thema, und das hier ist imho die letzte Erwähnung jenen Codes...

Und zwar vergleiche ich gerade diverse Pascal-Implementierungen des Boyer-Moore-Algos, bzw. deren unterschiedlichen Laufzeiten in Delphi einerseits und FreePascal andererseits, und dabei hab ich den hier aus dem Forum (TJsTextSearch aus der Code-Libary) mitverglichen.

So in der Form, wie er dort in der Code-Library steht, ist leider immer noch ein Fehler drin: der Algo funktioniert so leider nur für Wörter, in denen sich keine Buchstaben wiederholen, zuverlässig ("Delphi"). Sobald ein Buchstabe mehrfach im Suchbegriff vorkommt, gehts manchmal daneben, weil die SkipTable falsch aufgebaut wird ("Delphi Praxis" mit zwei "i"). Damit der Algo richtig funktioniert, muss die SkipTable andersrum aufgebaut werden (also for iCnt := 1 to Length(SubStr) do). Wollte ich nur mal anmerken, falls sich noch jemand anders mal wundern sollte, warum der Algo je nach Start-Offset mal etwas findet, mal nichts. Vielleicht kanns ja jemand bestätigen und dann in der Code-Library verbessert werden ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz