Probleme beim erstellen einer Datei



  • Nabend,
    ich hab eine Funktion geschrieben die eine Datei festgelegter Größe erstellt und nun würde ich gerne vorher noch überprüfen ob diese Datei bereits existiert. Ich benutze fopen mit dem mode -w um die Datei zu erstellen und weiß auch, dass man mit -rb einen Nullzeiger zurück bekommt wenn die Datei schon existiert, aber dann muss ich ja zweimal fopen aufrufen bzw die Datei zweimal öffnen. Einmal im readmode um zu überprüfen ob die Datei existiert und einmal mit schreib-und leserechten um die zu erstellen. Dann funktioniert aber alles nicht mehr wie es soll. Gibt es da vielleicht eine andere Möglichkeit solche Fehler abzufangen oder hab ich nen Denkfehler drin?
    Desweiteren habe ich noch eine Frage zu Datentypen bezüglich der Größe von Dateien, und zwar kann ich mit eben dieser Funktion Dateien bis ca 100MB erstellen aber darüber hinaus bekomme ich einen Speicherzugriffsfehler. Die Größe der Datei lege ich fest indem ich in einer Variable vom Typ long mit malloc Speicher reserviere und dann in die Datei schreibe. Woran könnte das liegen, dass das für sehr große Werte nicht mehr funktioniert?
    Ich bin dankbar für jeden Tip 😉


  • Mod

    filzstift schrieb:

    Nabend,
    ich hab eine Funktion geschrieben die eine Datei festgelegter Größe erstellt und nun würde ich gerne vorher noch überprüfen ob diese Datei bereits existiert. Ich benutze fopen mit dem mode -w um die Datei zu erstellen und weiß auch, dass man mit -rb einen Nullzeiger zurück bekommt wenn die Datei schon existiert, aber dann muss ich ja zweimal fopen aufrufen bzw die Datei zweimal öffnen. Einmal im readmode um zu überprüfen ob die Datei existiert und einmal mit schreib-und leserechten um die zu erstellen. Dann funktioniert aber alles nicht mehr wie es soll. Gibt es da vielleicht eine andere Möglichkeit solche Fehler abzufangen oder hab ich nen Denkfehler drin?

    Interpretation: Du möchtest prüfen, ob eine Datei existiert, ansonsten möchtest du diese überschreiben? Falls ja: Was soll andernfalls passieren?

    Mit streng portablen Standardmitteln ist fopen der einzige Weg. Ansonsten kannst du Betriebssystemmethoden benutzen, mit denen das einfacher geht. Mit ein paar ifdefs in der Prüffunktion braucht das auch nicht unportabel zu sein.

    Woran könnte das liegen, dass das für sehr große Werte nicht mehr funktioniert?

    An einem Fehler im Programm.



  • Nicht ganz, ich möchte prüfen ob die Datei bereits existiert, wenn ja dann soll eine Fehlermeldung ausgegeben werden, wenn nicht soll diese Datei erstellt werden. Also ich würde das ganz gerne mit fopen lösen. Muss ich denn dann 2 Zeiger auf FILE erstellen und bei denen jeweils fopen aufrufen um halt einmal mit -r den Nullzeiger zu prüfen ob die Datei schon existiert und mit den Schreibrechten die Datei ggf. zu erstellen? Oder kann man die Rechte irgendwie ändern während man eine Datei geöffnet hat?

    //Edit:
    Zu meiner anderen Frage:
    Die Speicherzugriffsverletzung liegt ja wohl am malloc, hab ich da irgendwas gravierend falsch gemacht:

    unsigned long *size = (unsigned long*)malloc(sizeof(unsigned long)*(blocksize*blockcount));
    

  • Mod

    Reine Existenz kannst du mit fopen im Lesemodus prüfen (mal angenommen, die Datei hat keine verrückten Rechte, die Schreiben erlauben, aber Lesen verbieten). Du kannst damit aber nicht Prüfen, ob du auch reinschreiben darfst. Dazu müsstest du logischerweise versuchen, sie auch schreibend zu öffnen. Also erst Lesen Existenz prüfen, dann Schreibend Schreibrecht prüfen. Im append-Modus wird die Datei dabei noch nicht einmal verändert (außer eventuelle Timestamps).

    Da du hier einen Fehler bei Existenz ausgeben willst, reicht es dir aber, sie einfach einmal Lesend zu öffnen. Bei Nichtexistenz erstellst du sie dann neu.

    Versuch am besten auch, Dateien nicht mehrmals gleichzeitig zu öffnen. Das könnte nämlich fehlschlagen.

    Rechte kennt Standard-C überhaupt nicht, das ist reine Betriebssystemsache und muss daher mit entsprechenden Funktionen behandelt werden. Jedenfalls wäre es ein Fehler, erst irgendwelche Rechte zu prüfen und sich dann im späteren Programmverlauf auf diese Rechte zu verlassen, denn sie könnten sich durch äußere Faktoren verändern. Ein Datei ist genau dann erfolgreich geöffnet worden, wenn fopen das sagt. Nicht wenn du dir denkst, dass du sie aufgrund früherer Informationen erfolgreich öffnen solltest.



  • Vielen Dank, hast mir sehr geholfen. Das mit dem Prüfen der Datei funktioniert jetzt 🙂



  • Ich hätte da doch noch eine weitere Frage zum selben Thema. Ich lese über die Kommandozeile einen Pfad als Zeiger auf char ein und wenn ich dann während der Ausführung nur einen Dateinamen ohne Pfad angebe erstellt mir die Funktion die gewünschte Datei im selben Verzeichnis, was auch korrekt ist. Bei angabe eines Pfads zb /home/.../test funktioniert das dann aber nicht mehr, also fopen liefert mir einen Nullzeiger. Der ganze Pfad befindet sich wie gesagt in einer Variablen datei und dann rufe ich halt fopen(datei,..) auf. Muss ich die Zeichenkette da vorher vielleicht irgendwie zerteilen oder so?


  • Mod

    filzstift schrieb:

    Muss ich die Zeichenkette da vorher vielleicht irgendwie zerteilen oder so?

    Nein, das darfst du sogar ausdrücklich nicht machen. Deiner prosaischen Beschreibung nach müsste es funktionieren. Es wird wohl ein Fehler in der technischen Umsetzung sein.



  • Ok, also gekürzt sieht das ganze so aus:

    char *name; //wird als Parameter der Funktion übergeben
    strcat(name,".c");
    FILE *datei = fopen(name,"w");
    

    Der Parameter bekommt das Argument aus der Kommandozeile übergeben. Wenn ich mir die Zeichenkette ausgeben lasse ist die korrekt, z.b. "/home/test.c". Aber das kann wohl nicht geöffnet werden. Wenn ich hingegen nur "test.c" eingebe klappt es..



  • Du solltest am String aus der Kommandozeile nichts ändern, da er nicht "dein Eigentum" ist und wohl mit gerade ausreichend großen Speicher reserviert wurde, sodass ein Anfügen weiteren Inhalts sogar zu einem Fehler führen könnte.
    Stattdessen solltest du eine Kopie mit größeren Speicher erstellen und dort deine Änderung vornehmen.

    // Includes
    #include <stdio.h>  // FILE, fopen, fclose, printf
    #include <stdlib.h> // malloc
    #include <string.h> // strcpy, strcat
    
    // Program entry
    int main(int argc, char** argv){
        // Declarations
        char *filename;
        FILE *file;
        // Any program parameter?
        if(argc > 1){
            // Copy first program parameter to new memory
            filename = (char*)malloc(strlen(argv[1]) + 3);  // Reserve enough memory for old content + 2 characters
            strcpy(filename, argv[1]);
            // Append text
            strcat(filename, ".c");
            // Open file in read mode
            file = fopen(filename, "r");
            // Could open file?
            if(file){
                // Message on successfull file opening
                printf("Could open file \"%s\"!", filename);
                // Close file
                fclose(file);
            }
            // Free memory
            free(filename);
        }
        // Program ends with positive error status
        return 0;
    }
    


  • Danke, das hilft mir schonmal ein wenig weiter. Das funktioniert jetzt aber nur für Dateien die entweder im selben Verzeichnis wie die C-Datei liegen oder in einem Ordner in diesem Verzeichnis, d.h. ich kann keinen absoluten Pfad wie "/home/../abc/test.c" angeben. Warum ist das so? Zudem krieg ich auch noch einen Nullzeiger zurück wenn ich als erstes Zeichen ein "/" schreibe, also "abc/test.c" funktioniert aber "/abc/test.c" nicht.


  • Mod

    filzstift schrieb:

    Danke, das hilft mir schonmal ein wenig weiter. Das funktioniert jetzt aber nur für Dateien die entweder im selben Verzeichnis wie die C-Datei liegen oder in einem Ordner in diesem Verzeichnis, d.h. ich kann keinen absoluten Pfad wie "/home/../abc/test.c" angeben. Warum ist das so? Zudem krieg ich auch noch einen Nullzeiger zurück wenn ich als erstes Zeichen ein "/" schreibe, also "abc/test.c" funktioniert aber "/abc/test.c" nicht.

    Das sollte nicht so sein. Lass dir mal zum Testen den fertigen Dateinamen im Programm angeben. Sind im Pfad zufällig Whitespace oder sonstige Sonderzeichen? Hast du die beim Aufruf auch korrekt angegeben? Hast du überhaupt Schreibrechte in dem Pfad?



  • Ahh ich hatte jetzt bloß noch einen Fehler in der Pfadangabe, hab mich einfach im Verzeichnis vertan und das existierte dann natürlich nicht 🙄 Danke nochmal, funktioniert jetzt wie es soll 🙂


  • Mod

    filzstift schrieb:

    Ahh ich hatte jetzt bloß noch einen Fehler in der Pfadangabe, hab mich einfach im Verzeichnis vertan und das existierte dann natürlich nicht 🙄 Danke nochmal, funktioniert jetzt wie es soll 🙂

    Off Topic: Die Funktion der Tabulatortaste in Konsolen kennst du?



  • Ja klar, sollte ich nur vielleicht auch mal anwenden 😉


Anmelden zum Antworten