dateien schreiben und lesen



  • hallo wie schon genannt sitz ich am problem binärdateien zu schreiben und wieder zu lesen.
    ich habe eine struktur namens personen dort sind z.b name vorname alter gespeichert

    struct personen
    {
    	char Vname[20];
    	char Name[20];
    	int Alter;
    	int Tel;
    } p1;
    

    nun habe ich eine funktion geschrieben die diese struktur mit werten füllt

    void eingabe_struct(struct personen *p1)
    {
    		puts("Vname: ");
    		scanf("%s",p1->Vname);
    		fflush(stdin);
    
    		puts("Name: ");
    		scanf("%s",p1->Name);
    		fflush(stdin);
        // Ausgabe von zahlen in der datei kommen iwie komische zeichen raus^^
    		puts("Alter: ");
    		scanf("%d",&p1->Alter);
    		fflush(stdin);
    
    		puts("Tel.: ");
    		scanf("%d",&p1->Tel);
    		fflush(stdin);
    }
    

    nun ist mein problem den vektorinhalt in eine datei zu schreiben
    void datei_ausgabe(struct personen *p1,FILE *f)
    {

    fwrite(p1,sizeof(*p1),1,f); // so hab ich es gelöst^^

    }

    void datei_oeffnen(void)
    {
    FILE *f;

    f=fopen("test.txt","wb+");
    if(f==NULL)
    {
    puts("DateiOpen-Fehler!!");
    }
    else
    {
    datei_ausgabe(&p1,f);
    fclose(f);
    }

    exit(-1);

    }
    und dazu eine funktion die den dateiinhalt in den vektor einliest

    danke



  • Hallo,

    die Struktur wird genau so in die Textdatei geschrieben, wie sie im Speicher liegt und zwar byteweise. Beim Datentyp char gibt's da keine Probleme, bei den anderen schon.

    Mein Lösungsvorschlag wäre die Benutzung von fprintf :

    // in die Datei schreiben
    fprintf (f, "%-20s %-20s %d %d",p1.Vname, p1.Name, p1.Alter, p1.Tel);
    
    // aus der Datei lesen
    fscanf (f, "%20s %20s %d %d", p1.Vname, p1.Name, &p1.Alter, &p1.Tel);
    

    Gez. monstermunchkin



  • // Ausgabe von zahlen in der datei kommen iwie komische zeichen raus^^
    

    Das ist normal, wenn im Binärformat geschrieben wird, kein Problem.



  • tHaboss schrieb:

    und dazu eine funktion die den dateiinhalt in den vektor einliest
    danke

    das selbe in grün mit fopen( "xx", "rb" ) und fwrite
    bitte.

    0asfdaß



  • Du solltest lieber getchar statt scanf benutzen und zwei char* statt char[] in Kombination mit malloc benutzen. Wenn jemand einen Vor- oder Nachnamen mit mehr als 19 Zeichen hat ist deine Struktur futsch. Sowas nennt sich Pufferüberlauf: http://de.wikipedia.org/wiki/Pufferüberlauf und sollte auf jeden Fall vermieden werden.

    Ich weiß auch nicht was genau du mit Vektor meinst.

    Wenn du aus der Datei die Struktur wieder einlesen willst gibt es 2 Varianten.

    1. Du lässt den Fehler in der Struktur stehen und benutzt

    struct personen{
        char Vname[20];
        char Name[20];
        int Alter;
        int Tel;
    } p1;
    const char* datei = "pfad/datei";
    f = fopen(datei, "rb");
    if (f) fread(&pl, sizeof(struct personen), 1, f);
    else printf("fehler beim lesen von %s\n", datei);
    fclose(f);
    

    Oder du machst es richtig und schreibst sowas wie

    struct personen{
        char* Vname;
        char* Name;
        int Alter;
        int Tel;
    } p1;
    
    char *readline(FILE* f){ //lese eine Zeile Text ein
        char *buffer, *tempbuffer;
        int buffersize = 32, maxbuffersize = 1<<12;
        int i, t, fertiggelesen = 0;
        if (!buffer = malloc(buffersize)) exit(printf("Fehler: Speicher ist alle"));
        while (1){
            for (i = 0; i<buffersize-1; i++){
                t = fgetc(f);
                if (t==EOF) exit(printf("Datei %s ist kaputt\n", datei));
                else buffer[i] = (char)t;
                if buffer[i] = '\n'{ //Zeile zuende
                    buffer[i+1] = '\0';
                    tempbuffer = buffer;
                    if (!buffer = malloc(strlen(tempbuffer)+1)) exit(printf("Fehler: Speicher ist alle"));
                    strcpy(buffer, tempbuffer);
                    free(tempbuffer);
                    return buffer;
                }
            }
            //buffer hat nicht gereicht
            if (buffersize=<<1 > maxbuffersize) exit(printf("Fehler: Zeile in Datei %s ist zu lang\n", datei));
            tempbuffer = buffer;
            if (!buffer = malloc(strlen(tempbuffer)+1)) exit(printf("Fehler: Speicher ist alle"));
            strcpy(buffer, tempbuffer);
            free(tempbuffer);
        }
    }
    
    const char* datei = "pfad/datei";
    //laden
    FILE *f = fopen(datei, "r");
    p1->Vname = readline(f);
    p1->Name = readline(f);
    p1->Alter = stringtoint(readline(f));
    p1->Tel = stringtoint(readline(f));
    fclose(f);
    //speichern:
    f = fopen(datei, "w");
    fprintf(f, "%s\n%s\n%d\n%d\n", p1->Vname, p1->Name, p1->Alter, p1->Tel);
    fclose(f);
    

    Fehlt noch die Mainfunktion und vielleicht sollte readline return 0 statt exit nutzen wenn es schief geht, und es ist natürlich nichts davon getestet, aber die Idee sollte klar sein. Ist natürlich aufwendiger alles, aber dafür funktioniert es immer oder sagt wieso es nicht geht statt eine Sicherheitslücke aufzureißen.



  • Die Arraygrenzen absichern sollte man schon, aber die größen der Arrays sind doch fest vorgegeben, malloc zu bemühen ist ein bisschen weit hergeholt.
    Wenn man für das Einlesen einen Puffer wählt der groß genug ist, dann braucht man den Eingabepuffer nicht zu leeren, weil nix im Eingabepuffer übrig bleibt.

    char buf[BUFSIZ]; // BUFSIZ ist in stdio.h definiert und gibt die Größe des Eingabepuffers an.
    

    Gruß,
    B.B.



  • nwp2 schrieb:

    Du solltest lieber getchar statt scanf benutzen und zwei char* statt char[] in Kombination mit malloc benutzen. Wenn jemand einen Vor- oder Nachnamen mit mehr als 19 Zeichen hat ist deine Struktur futsch. Sowas nennt sich Pufferüberlauf: http://de.wikipedia.org/wiki/Pufferüberlauf und sollte auf jeden Fall vermieden werden.

    Man kann auch einfach nur 19 Zeichen einlesen:

    ...
    scanf ("%19s", p1.Vname);
    scanf ("%19s", p1.Name);
    ...
    


  • oda mit fgets begrenzen. fgets ist noch etwas flexibla!



  • danke für eure hilfe ich werde mich melden sobald neue problem auftreten oder wenn sich etwas ändern sollte^^



  • also ich hab mich wieder damit beschäftigt diesmal kam etwas effektives raus ^^

    void main(void)
    {	
        FILE *d;
        struct person vec[20];    // mein angelegter strukturvektor 
    
    	eingabe_struct(&p1);  // struktur füllen
    	ausgabe_struct(&p1); 
    	d=datei_oeffnen();  // datei im binärmodus zum schreiben öffnen	 	
    	datei_ausgabe(vec,d);     //text in datei schreiben         
    	fclose(d);
    
    }
    
    void datei_ausgabe(struct person *vec,FILE *f)
    {
    	int i=0;                      
                                         // Schleife
    	//for(i=0;i<sizeof();++i);  // gescheiterter versuch
    
    	fwrite(&vec+i,sizeof(struct person),1,f);
    	fprintf(f, "%s %s %d %d\n",p1.Vname,p1.Name,p1.Alter,p1.Tel);
    	printf("\n\nLaenge: %d",i);
    }
    
    FILE* datei_oeffnen(void)   //verändert          
    {
    	FILE *f;
    
    	f=fopen("test.dat","w+b");
    	if(!f)
        {
           puts("DateiOpen-Fehler!!");
    	   //exit(2);
        }
        return f;
    }
    
    void eingabe_struct(struct person *p1)
    {
    	char c;
    	do{
    		puts("Vname: ");
    		scanf("%10[^\n]",p1->Vname);
    		fflush(stdin);
    
    		puts("Name: ");
    		scanf("%10[^\n]",p1->Name);
    		fflush(stdin);
    
    		puts("Alter: ");
    		scanf("%d",&p1->Alter);
    		fflush(stdin);
    
    		puts("Tel.: ");
    		scanf("%d",&p1->Tel);
    		fflush(stdin);
    
    		printf("Ende (ENTER) oder bel. Eingabe ");
    	}while ((c=getch())!='\r');
    }
    void ausgabe_struct(struct person *p1)
    {
    	printf("\nVorname: %s\n", p1->Vname);
    	printf("Name: %s\n", p1->Name);
    	printf("Alter: %d\n", p1->Alter);
    	printf("Telefon: %d\n", p1->Tel);
    
    }
    
    mein problem ist halt wen ich jetz die datei öffne und den code krieg sieht das iwie komisch aus mit so häsligen zeichen^^
    
    AUSGABE:
    

    00000000 24 FD 12 00 48 14 31 10 62 FB 41 5F 91 5D CA 01 $...H.1.b.A_.]..
    00000010 00 E0 FD 7F CC CC CC CC CC CC CC CC 66 65 6C 69 ............feli
    00000020 78 20 6D 75 73 74 65 72 20 32 30 20 32 32 31 32 x muster 20 2212
    00000030 0A
    [cpp]

    ist das normal das vor meinem eigentlich eingegebenen text : felix muster 20 2212 solche komischen zeichen kommen ?

    danke

    thaboss



  • Hallo,

    ist das normal das vor meinem eigentlich eingegebenen text : felix muster 20 2212 solche komischen zeichen kommen

    Nein, aber du solltest dich schon entscheiden, ob du mit fwrite oder mit fprintf (dann musst du die Datei nicht binär mit +b öffnen) in die Datei schreiben willst. Dann ist auch noch ein "&" zu viel:

    fwrite(vec+i,sizeof(struct person),1,f);
    

    MfG,

    Probe-Nutzer


Anmelden zum Antworten