fopen counter



  • Hi,

    meine C Kenntnisse sind leider sehr gering, ich programmiere eher PHP, musste aber nun eine lib für eine Software schreiben, welche als Modul beim Start der Software geladen wird.

    Ich poste 2 Codeausschnitte, der erste liest die Zahl einer Datei ein, erhöht diese +1. im 2ten Codeausschnitt wird der erhöhte Wert zurückgeschrieben.
    Es ist im grunde eine Zählfunktion, wie oft eine bestimmte Aktion ausgeführt wird.

    Lesen:

    mutex_lock();
    
    FILE *f_last_id_read;
    unsigned long last_id;
    if((f_last_id_read = fopen("/var/lib/ldap-notifier/last_transaction_id", "r")) == NULL) {
    	mutex_unlock();
    	return;
    }
    
    char buf[sizeof(long)];
    fread(buf, sizeof(long), 1, f_last_id_read);
    fclose(f_last_id_read);
    
    last_id = atoi(buf) + 1;
    

    Schreiben:

    // Write last_id:
    FILE *f_last_id_write;
    if ((f_last_id_write = fopen("/var/lib/ldap-notifier/last_transaction_id", "w")) == NULL) {
    	Debug( LDAP_DEBUG_ANY, "auditlog translog(): Cannot write /var/lib/ldap-notifier/last_transaction_id!!!\n", 0, 0, 0 );
    	ldap_pvt_thread_mutex_unlock(&ad->ad_mutex);
    	return;
    }
    fprintf(f_last_id_write, "%d", last_id);
    fclose(f_last_id_write);
    
    mutex_unlock();
    

    Im Grunde interessiert mich, ob es bedenken bei diesem Code gibt?

    Mir ist dabei nur eine Situation aufgefallen, der Counter ist bei einem Testlauf von 3 auf 39 gesprungen, ab 39 hat er normal weitergezählt..

    Danke!

    lG



  • fread ist nicht das Gegenstück zu fprintf : http://www.cplusplus.com/reference/cstdio/fread/

    Mit fread werden Binärwerte eingelesen. Also so, wie der Computer das intern speichert.

    Wenn es menschenlesbar sein soll, dann

    fscanf(last_id_read,"%d", &last_id);      // lesen
    
    fprintf(f_last_id_write, "%d", last_id);  // schreiben
    

    Wenn last_id ein long ist, ist %ld der richtige Formatspecifier.
    Wenn last_id ein unsigned long ist, ist %lu der richtige Formatspecifier.

    Wenn es binär sein soll:

    fread( &last_id, sizeof(last_id), 1, last_id_read);      // lesen
    
    fwrite(&last_id, sizeof(last_id), 1, f_last_id_write);      // schreiben
    

    Evtl. musst du das +1 nach dem lesen noch einbauen.



  • Nimm direkt fscanf :

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
            FILE*f_last_id_read;
            unsigned long last_id;
            if(!(f_last_id_read=fopen("bla","r")))
            {
                    fclose(f_last_id_read);
                    exit(EXIT_FAILURE);
            }
            if(!fscanf(f_last_id_read,"%lu",&last_id))
            {
                    fclose(f_last_id_read);
                    exit(EXIT_FAILURE);
            }
    
            printf("ID: %lu\n",last_id);
    
            fclose(f_last_id_read);
            exit(EXIT_SUCCESS);
    
    }
    

    Den Rest hat DirkB schon gesagt.



  • dachschaden schrieb:

    if(!fscanf(f_last_id_read,"%lu",&last_id))
    

    Ja, ja, die Fehlererkennung.
    Im Erfolgsfall gibt fscanf hier eine 1 zurück. Alles andere wäre ein Fehler.

    fscanf return Value schrieb:

    If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.

    Wenn die Datei leer ist kommt ein EOF.
    EOF ist nicht Null.

    Darum

    if(1 != fscanf(f_last_id_read,"%lu",&last_id))
    


  • Ach geil, daran habe ich jetzt überhaupt nicht gedacht. Danke, DirkB. 🙂



  • Hi,

    danke für eure Antworten!

    ist es auch möglich, dass lesen & schreiben mit einem fopen durchzuführen?

    habe schon einiges probiert mit rewind & co, aber er hängt die neue Zahl immer hinten dran.. 😞

    lG



  • Das funktioniert, wenn der Modus ungleich append und für Lesen+Schreiben geeignet.
    Zusätzlich muss beim Wechsel zw. Lesen+Schreiben Operationen noch ein explizites flush passieren.



  • DBGTMaster schrieb:

    ist es auch möglich, dass lesen & schreiben mit einem fopen durchzuführen?

    Mit "r+" als Mode geht das.

    DBGTMaster schrieb:

    habe schon einiges probiert mit rewind & co,

    Musst du auch weiterhin nehmen

    DBGTMaster schrieb:

    aber er hängt die neue Zahl immer hinten dran.. 😞

    Welchen Mode hattest du denn?

    Du musst aber aufpassen. Es werden Bytes überschrieben, (keine Zeilen oder so). Die Datei wird dadurch nicht kürzer.
    Du solltest entweder beim fprintf ein \n oder Leerzeichen am Ende mit ausgeben oder/und eine Längenangabe beim Formatspecifier angeben.

    fprintf(f_last_id_write, "%10d\n", last_id);  // schreiben
    


  • Oh danke, nun funktionierts doch!

    lG


Anmelden zum Antworten