Grosse Datei durchsuchen

  • Themenstarter Themenstarter spex
  • Beginndatum Beginndatum
S

spex

Hi,

ich hab eine 900KB grosse Datei die ich gerne nach einem Wort durchsuchen möchte.
Dann brauche ich die Position des Wortes.

Wie mache ich das am besten, ich kann die Datei wohl kaum komplett in einen String lesen und dann durchsuchen mit STRING.find();

Hab das bereits mit einem while(!eof()) versucht, geht aber nicht.

Gibts da eine praktikable und performante Lösung?
Ich verwende fopen, fseek, fclose, fgets.

Gruss - sp3x
 
Hi,
was spricht denn dagegen die Datei Zeilenweise durch zugehen und
jede Zeile nach dem Wort zu durchsuchen? Oder kann das Wort auch
durch einen Zeilenumbruch getrennt sein ?
Dann würde ich evtl. einen kleinen Automaten Bauen dessen Zustände
den Buchstaben des Wortes entsprechen das du suchst und dann auch
wieder zeilenweise durch die Datei gehen.

Gruß Benny
 
ich schließe aus deinen Befehlen, dass du C verwendest?(nicht c++) mit !eof ist so eine Sache... aber prinzipiell spricht doch nichts gegen ein zeilenweises auslesen(?) Ist vllt nicht die beste Lösung aber wozu willst du das mit Performance haben? und nunja... DurchSUCHEN musst du die File ja in jedem Fall, ansonsten würdest du ja das Wort nicht finden, warum also nicht zeilenweise auslesen, in einem array speichern, array durchsuchen und array wieder mit einer neuen Zeile füllen,

lg
 
Das Problem ist das die Datei ansich keine offiziellen Zeilenumbrüche hat. Im Prinzip ist es eine binäre Datei die aber auch ASCII Zeichen enthält, unteranderem ein Wort das aber so nicht aufzufinden ist, also keine feste Position in der Datei hat, die Position kann also vareieren.

Das Wort das ich suche hat aber ein Prefix, das ist immer das selbe. Nun möchte ich die Datei nach diesem Prefix durchsuchen und nach der Position des Prefix's das Wort auslesen was ich eigendlich suche.

Verstanden 8D ?

Wenn ich nun also in Blöcken auslese (z.B 1024Byte), dann kann es passieren das ich unglücklicherweise das Wort genau in der Mitte trenne und dann kann ich es nichtmehr finden.
 
Hi,

bau dir doch einen kleine Automaten wie ich schon oben vorgeschlagen hab.
Könnte man irgendwie so ähnlich wie im folgenden
pseudocode aussehn:

Code:
char* detect = "markierung";
int c = 0;

while( read line ) {

  foreach byte in line{

   if ( byte == detect[cur] ) {
     cur++;
     if( cur == strlen(detect) ){
       // wort gefunden;
     }
   } else {
      cur =  0;
   }

 }


}
Benny
 
Also so lese ich nun die Datei ein:
Code:
   FILE *fFile;
    char *buff;
    long size;

    fFile = fopen("test.dat", "rb");

        fseek (fFile , 0 , SEEK_END);
        size = ftell(fFile);
        rewind(fFile);

        buff = (char *) malloc(sizeof(char)*size);

        fread(buff, 1, size, fFile);

    fclose(fFile);

Das funktioniert auch wunderbar und auch "\0" werden ignoriert die den String abbrechen könnten. Nun weis ich aber net wie ich das Array "buff" nun durchsuchen kann. Ich hab es bereits probiert es mit:
Code:
string tmp = buff;
in einen String zu kopieren und hier die find() Funktion zu nutzen.
Nun kopiert er aber nur die ersten 4Byte aus dem "buff" weil dann ein "\x00" bzw "\0" kommt.

Wie kann ich also am einfachsten das CharArray "buff" nach einer Zeichenfolge durchsuchen?

Gruß
 
Um mein Problem nochmal darzustellen:
Ich hab nun einen Pointer der auf ein CharArray im Speicher verweist in das ich meine Binäre Datei geladen habe.
Nun mächte ich dieses Array duchsuchen nach einer Zeichenfolge z.B.: "Hallo".

Folgende Funktion konnte ich auftreiben:
Code:
typedef uint8_t     u8;
Code:
u8 *find_data(u8 *buff, int buffsz, u8 *str) {
    int     strsz;
    u8      *limit;

    strsz = strlen(str);
    limit = buff + buffsz - strsz;

    for(; buff <= limit; buff++) {
        if(!memcmp(buff, str, strsz)) return(buff);
    }
    return(NULL);
}

Diese scheint auch zu funktionieren, allerdings nur mit einem C Kompiler (GCC), bei G++ gibts Probleme weil er folgenden Fehlerausgibt:
error: invalid conversion from `u8*' to `const char*'|

Außerdem versteh ich die Funktionsweise nicht so ganz, vorallem die von memcmp die ja Speicherblöcke vergleicht, nur kann ich mir darunter nicht viel vorstellen.
 
Hm sieht ja (vgl. string) danach aus, dass du C++ verwendest. (Wenn du mit C++ einließt, ist eh alles im FileStreamBuffer ;) )

Ich würde behaupten, dass ist zu viel Aufwand, wie der das macht ;)
C++:
#include <cstring>

const char* find_data(const char* ptr_buffer, const std::size_t buffer_size, const char* ptr_string) 
{
    const std::size_t string_size(std::strlen(ptr_string));
    
    for (const char* ptr_end(ptr_buffer + buffer_size - string_size + 1); ptr_buffer < ptr_end; ++ptr_buffer) if (std::memcmp(ptr_buffer, ptr_string, string_size) == 0) return ptr_buffer;

    return NULL;
}
...
 
Zurück