binärdatei nach zeichenkette durchsuchen



  • hallo,

    ich hab eine binärfile, welche ich nach einer bestimmten zeichenfolge absuchen möchte.
    wenn vorhanden soll der dateidescriptor auf den anfang der zeichenkette z.b. "abc" gesetzt werden und dann die genannte zeichenkette mittels einer anderen zeichenkette von konstanter länge (wie hier auch 3 bytes) überschrieben werden.

    welche funktionen könnte ich für mein vorhaben nutzen?

    ich hatte sonst immer zeilenwise eingelsen und diese dann abgesucht, aber das bei einer binärdatei wird wohl schlecht gehen?

    cu...



  • Machs dir nicht zu schwer.
    Nehmen wir an, dein Suchwort ist x Zeichen lang und die Datei ist auch mindestens x Zeichen lang.


    Filepointer an Anfang setzen und mit mit fread x Zeichen einlesen.
    Dann mit strcat das Array mit Suchwort vergleichen.
    Wenn es nicht stimmt, filepointer (x-1) Zeichen zurück und nochmal das ganze.

    (Etwas Laufzeiteffizienter ist es, Zeichenweise zu suchen, bis der erste Buchstabe übereinstimmt.)



  • fseek, fread

    die suchmethode wirst du mit nem rotierenden buffer oder byteweise machen müssen.



  • Achso ja,

    wenn die Datei nicht allzu groß ist, lese sie komplett in den Speicher und lass einen strstr durchlaufen. Dann den ganzen Speicher wieder in die Datei schreiben.

    PS: Im vorigen Post habe ich strcmp gemeint, nicht strcat.



  • das prob ist, dass die position in der binärfile varieren kann.
    d.h. doch das es passieren kann das meine minizeichenkette durch den buffer zerschnitten wird und dann kein treffer herauskommt.

    die fssek-funktion hatte ich mir schon mal angesehen. ich komme nur noch nicht ganz mit dem dritten parameter (whence) zurecht.

    hat jemand mal bitte ein beispiel für mich?



  • @SeppSchrot: die datei ist ~ 350kb groß.

    ich möchte den arbeitsspeicher nicht allzuviel belasten (zumindest nicht die vollen 350kb).



  • stdin schrieb:

    @SeppSchrot: die datei ist ~ 350kb groß.

    ich möchte den arbeitsspeicher nicht allzuviel belasten (zumindest nicht die vollen 350kb).

    *lol* Sehr löblich. Vermutlich cachet das OS die Datei sowieso.

    Der 3. Parameter von fseek heißt origin und für ihn sind drei Werte zulässig:
    SEEK_SET - Der 2. Parameter gibt die Position vom Anfang der Datei gemessen an.
    SEEK_END - Dasselbe vom Ende der Datei aus gesehen.
    SEEK_CUR - Der 2. Parameter gibt relativposition zum derzeitigen Filepointer an. Also +1 ist das übernächste Byte, -1 wäre das Byte, das als letztes gelesen wurde.

    das prob ist, dass die position in der binärfile varieren kann.
    d.h. doch das es passieren kann das meine minizeichenkette durch den buffer zerschnitten wird und dann kein treffer herauskommt.

    Nein, wenn du Zeichenweise voranschreitest, nicht.
    Hast du kariertes Papier? Schreib mal einen kurzen Text rein und versuche das mal nachzuvollziehen.



  • stdin schrieb:

    das prob ist, dass die position in der binärfile varieren kann.
    d.h. doch das es passieren kann das meine minizeichenkette durch den buffer zerschnitten wird und dann kein treffer herauskommt

    Diese problem lässt sich leicht lösen. du brauchst die puffer nur um die länge der gesuchten zeichenkette überlappen lassen dann findest du die zeichenkette garantiert.
    zb länge 5-byte puffergrösse 512 bytes
    1. lese von offset 0 - 512 .. durchsuche puffer
    2. lese von offset 506 - 1018 ... durchsuche buffer
    usw
    btw suchen mit strstr ist nicht optimal da strstr bei vorkommen eines 0-bytes teminiert.

    Kurt



  • @ZuK

    irgenwie haut die siche bei mir mit strstr nicht hin:

    char * ptr;
    	char line_buffer[63];
    	while(fgets(line_buffer, sizeof(line_buffer), fd))
    	{
    		if((ptr = strstr(line_buffer, "socket")))
    		{
    			printf("POS: %i\n", ptr);
    		}
    	}
    

    der findet "socket" einfach nicht.

    das kann doch schon am terminierendem '\0' liegen, oder?



  • Wie gesagt wenn im puffer irgendwo vor der zeichenkette "socket" ein 0-byte steht dann findet strstr deinen string nicht. es wird dir nichts übrigbleiben und zeichenweise zu vergleichen bis du ein 's' findest, dann kannst du von dort aus strstr() verwenden um zu sehen ob es dein gesuchter string ist.
    Kurt



  • na dann werd ich wohl das mal probieren...



  • ZuK schrieb:

    stdin schrieb:

    das prob ist, dass die position in der binärfile varieren kann.
    d.h. doch das es passieren kann das meine minizeichenkette durch den buffer zerschnitten wird und dann kein treffer herauskommt

    Diese problem lässt sich leicht lösen. du brauchst die puffer nur um die länge der gesuchten zeichenkette überlappen lassen dann findest du die zeichenkette garantiert.
    zb länge 5-byte puffergrösse 512 bytes
    1. lese von offset 0 - 512 .. durchsuche puffer
    2. lese von offset 506 - 1018 ... durchsuche buffer
    usw
    btw suchen mit strstr ist nicht optimal da strstr bei vorkommen eines 0-bytes teminiert.

    Kurt

    @ZuK:
    also das mit dem zeichen einlesen dauert mir zu lange!
    gibts auf o.g. posting von dir ne andere möglichkeut zeichen in einem buffer zu suchen als mit strstr???



  • schneller wirds nur wenn du einen grösseren buffer verwendest.
    Kurt



  • ich sehe gerade du versuchst mit das file mit fgets() zu lesen. dasfunktioniert leider auch nicht. nimm fread().
    kurt



  • so ungefähr sollte es funktionieren. ungetestet.

    #include <stdio.h>
    #include <string.h>
    
    int main() { 
       FILE * fp = fopen("./m", "r,b" );
       char buffer[1024];
       char * to_find = "socket";
       int slen = strlen(to_find);
       int found = 0;
       int idx;
       char * p;
       long sp = 0;
       fseek(fp, 0, SEEK_END);
       long fsize=ftell(fp);
       // printf("size=%d\n", fsize);
       rewind (fp);
    
       int szread = fread(buffer,1,1024, fp );
       // printf("sp=%d length=%d\n", sp ,szread);
    
       while ( sp < fsize && ! found ) {
           p = buffer;
           for ( idx = 0; idx < szread; idx++ ) {
              if ( *p == to_find[0] ) {
    	     found = ( strstr( p, to_find ) == p );
    	     if ( found )
    	        break;
    	  }
    	  p++;
           }
           sp += ( 1024 - slen );
           fseek( fp, sp, SEEK_SET );
           szread = fread(buffer,1,1024, fp );       
           // printf("sp=%d length=%d\n", sp ,szread);
       }   
    }
    

    Kurt



  • danke kurt,

    funzt zwar nicht, aber ich hab wenigstens ein beispiel.

    irgendwie läuft fread auch nicht in der schleife ???

    edit: <sorry> funzt wunderbar 😃 😃 😃
    ich habe nur den ersten aufruf von fread in eine while-schleife gepackt und es klappt prima !



  • wenn du die printf aktivierst solltest du sehen dass das file zumindest komplett gelesen wird. Also soweit sollte es funktionieren. Bin mir nicht ganz sicher mit dem strstr.
    Kurt



  • stdin schrieb:

    ich habe nur den ersten aufruf von fread in eine while-schleife gepackt und es klappt prima !

    Dann musst du den zweiten aber weglassen.
    K



  • klappt 100% 😃

    ein problem hab ich noch:

    FILE * fd = fopen(file, "wb" );
    // Anfang des zu überschreibenden Bytes
    fseek( fd, end_offset, SEEK_SET );
    printf("%i\n", ftell(fd));
    putc('e', fd);
    fclose(fd);
    

    wenn ich mit putc oder mit fputc ein zeichen an die offset-position schreiben möchte macht er dies zwar, jedoch wird der anfang bis zu dieser pos. mit 0x00 aufgefüllt und der rest abgeschnitten.
    was mach ich flasch???



  • okay, hat sich erledigt, wenn man den access_mode nicht entsprechend setzt kann es ja auch nicht klappen <also manchmal> 🙄


Anmelden zum Antworten