Textdatei auslesen und eine andere Textdatei schreiben?



  • Ich muss ein c-programm schreiben, das aus eine Textdatei(verkehrsdaten.txt), die ständig ändert, die daten zeilenweise auslesen und in eine andere textdatei(feld.txt) schreibe. In der erste textdatei (verkehrsdaten.txt) kommen die einträge doppelt und mehrfach vor, und das will verhindern in der andere textdatei (feld.txt) vorzukommen. Die Textdateien sehen folgendermaßen aus:

    1. Quelle (verkehrsdaten.txt)

    A 192.168.0.84 5996 192.168.0.221 5890 0 user0 user1
    A 192.168.0.84 5996 192.168.0.221 5890 0 user0 user1
    A 192.168.0.84 5996 192.168.0.221 5890 0 user0 user1
    A 192.168.0.123 5062 192.168.0.135 5062 8 user3 user4
    A 192.168.0.123 5062 192.168.0.135 5062 8 user3 user4
    E 192.168.0.84 5890 192.168.0.84 5996 user0 user1
    A 192.168.0.123 5062 192.168.0.135 5062 8 user3 user4
    E 192.168.0.123 5062 192.168.0.135 5062 user3 user4
    A 192.168.0.151 10170 192.168.0.160 10466 0 user user2
    A 192.168.0.84 6000 192.168.0.221 5894 0 user user1
    A 192.168.0.221 5894 192.168.0.84 6000 0 user1 user
    A 192.168.0.221 5894 192.168.0.84 6000 0 user1 user
    E 192.168.0.221 5894 192.168.0.84 6000 user1 user
    E 192.168.0.151 10170 192.168.0.160 10466 user user2

    2. Ziel: (feld.txt)

    A 192.168.0.84 5996 192.168.0.221 5890 0 user0 user1
    A 192.168.0.123 5062 192.168.0.135 5062 8 user3 user4
    E 192.168.0.84 5890 192.168.0.84 5996 user0 user1
    E 192.168.0.123 5062 192.168.0.135 5062 user3 user4
    A 192.168.0.151 10170 192.168.0.160 10466 0 user0 user2
    A 192.168.0.84 6000 192.168.0.221 5894 0 user user1
    E 192.168.0.221 5894 192.168.0.84 6000 user1 user
    E 192.168.0.151 10170 192.168.0.160 10466 user0 user2

    ich habe mir folgendes gedacht:

    - Lese erste Zeile aus verkehrsdaten.txt ein
    - "A" oder "E"?
    wenn "A" ?
    - gibt es diese "A" Zeile in textdatei feld.txt schon mal?
    -> Nein: dann schreibe diese "A" Zeile in textdatei Feld.txt und lese die nächste zeile aus verkehrsdaten.txt ein.
    Ja-> gibt es zu diesr zeile "A" eine "E" im textdatei feld.txt
    -> Ja dann schreibe die "A" Zeile in textdatei feld.txt

    das ist die c-code die ich geschrieben habe:

    #include <stdio.h> 
    #include <unistd.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <fcntl.h> 
    #include <string.h> 
    
     //Variableninitialisierung
    FILE *file, *file1; 
    char data[256], ip1[32], ip2[32], port1[8], port2[8], IP1[32], 
    char IP2[32], codec[8], name1[8], name2[8], AorE[1]; 
    char Session1_ip1[32], Session2_ip1[32], Session3_ip1[32], 
    char Session4_ip1[32], Session5_ip1[32], Session6_ip1[32], 
    char Session7_ip1[32], Session8_ip1[32], Session9_ip1[32], Session10_ip1[32]; 
    char *ptr; 
    int n; 
    
    int main(void) 
    
    { 
    strcpy(Session1_ip1,"session1"); 
    strcpy(Session2_ip1,"session2"); 
    strcpy(Session3_ip1,"session3"); 
    strcpy(Session4_ip1,"session4"); 
    
    // open a txt file verkehrsdaten 
    file = fopen("/var/tmp/verkehrsdaten2","r"); 
    n=0; 
    
    while(1){     
    
        while(fgets (data, 256, file)) 
        {
    //hier werden die Daten zeilenweise aus der verkehrsdaten.txt gelesen
        ptr = strtok(data," "); 
        sprintf(AorE, "%s", ptr); 
    
            if(strstr(AorE, "A")!=NULL) 
            { 
                ptr = strtok(NULL," "); 
                sprintf(ip1, "%s", ptr); 
    
                ptr = strtok(NULL," "); 
                sprintf(port1, "%s", ptr); 
    
                ptr = strtok(NULL," "); 
                sprintf(ip2, "%s", ptr); 
    
                ptr = strtok(NULL," "); 
                sprintf(port2, "%s", ptr); 
    
                ptr = strtok(NULL," "); 
                sprintf(codec, "%s", ptr); 
    
                ptr = strtok(NULL," "); 
                sprintf(name1, "%s", ptr); 
    
                ptr = strtok(NULL," "); 
                sprintf(name2, "%s", ptr); 
    
    //feld.txt wird hier durch file1 zum schreiben geöffnet
                file1 = fopen("/var/tmp/feld","a"); 
    
    //beispielhafter Vergleich der Daten (funktioniert so nur für die ersten drei Zeilen!)
     if(strstr(Session1_ip1,ip1)==NULL && strstr(Session2_ip1,port1)==NULL && strstr(Session3_ip1,ip1)==NULL && strstr(Session4_ip1,port1)==NULL)
                {     
                fprintf(file1, "%s %s %s %s %s %s %s %s", AorE, ip1, port1, ip2, port2, codec, name1, name2); 
    
                    if(n==0){strcpy(Session1_ip1,ip1);strcpy(Session2_ip1,port1);} 
                            if(n==1){strcpy(Session3_ip1,ip1);strcpy(Session4_ip1,port1);} 
                            n++; 
                    } 
                    fclose(file1); 
                    } 
    
     //alternative Behandlung, wenn eine Zeile mit "E" markiert ist
                    if(strstr(AorE, "E")!=NULL) 
                    { 
                        ptr = strtok(NULL," "); 
                        sprintf(IP1, "%s", ptr); 
    
                        ptr = strtok(NULL," "); 
                        sprintf(port1, "%s", ptr); 
    
                        ptr = strtok(NULL," "); 
                        sprintf(IP2, "%s", ptr); 
    
                        ptr = strtok(NULL," "); 
                        sprintf(port2, "%s", ptr); 
    
                        ptr = strtok(NULL," "); 
                        sprintf(name1, "%s", ptr); 
    
                        ptr = strtok(NULL," "); 
                        sprintf(name2, "%s", ptr); 
    
                        file1 = fopen("/var/tmp/feld","a"); 
                        fprintf(file1, "%s %s %s %s %s %s %s", AorE, IP1, port1, IP2, port2, name1, name2); 
                        fclose(file1); 
    
                    } 
                        if(strstr(Session1_ip1,IP1)!=NULL && strstr(Session2_ip1,port1)!=NULL) {n=0;} 
                         if(strstr(Session3_ip1,IP1)!=NULL && strstr(Session4_ip1,port1)!=NULL) {n=1;} 
            } 
    
        } 
    fclose(file); 
    }
    

    hat jemand eine ideee wie man das programmieren kann. ?



  • Du hast irgendwie vergessen, eine konkrete Frage zu stellen bzw. das Fehlverhalten, das eventuell in deinem Programm vorkommt, zu beschreiben...



  • das klein c-programm tut nicht was ich wollte! und zwar schreibt immer noch die doppelte oder mehrfach vorkommene zeilen von textdatei verkehrsdaten.txt in textdatei feld.txt. die frage ist wie kann ich es verhindern diese zeilen (verkehrsdaten.txt) mit "A" vorne, die mehrfach vorkommen in der textdatei feld.txt zu schreiben ?? hoffe, dass ich die frage deutlich gestellt habe.



  • Wenn die Datei nicht so groß ist,
    würde ich sie komplett in den Speicher in eine Tabelle lutschen.
    Des weiteren würde ich beim schreiben jeden Satz in
    eine 2. Tabelle tüteln.
    diese Tabelle dann vor dem schreiben mit dem Satz, der gerade geschrieben
    werden soll, durchsuchen, und wenn schon drin, weiter in der
    Tabelle mit den eingelesenen Datensätzen. Noch einfacher wirds, wenn
    eine relationale Datenbank angebunden werden kann.
    Die Sätze einlesen, in Tabelle schreiben und dann mit
    select distinct... wieder auslesen und wegschreiben.



  • azoul schrieb:

    Ich muss ein c-programm schreiben, das aus eine Textdatei(verkehrsdaten.txt), die ständig ändert

    Werden die Daten immer angehängt? Spart auch viel Zeit, wenn du nur die dazu kommenden Zeilen checkst.
    Die strtok Aufrufe kannst du mit einer Zeile sprintf ersetzen, macht das ganze kürzer und leserlich.
    Die Zeilen kannst du mit strcmp vergleichen. Wenn es auf Geschwindigkeit ankommt, kannst du binäres Suchen oder ein Hashverfahren implementieren.



  • Ja die Daten werden immer angehängt..

    Die strtok Aufrufe kannst du mit einer Zeile sprintf ersetzen, macht das ganze kürzer und leserlich.

    wie mache ich das? Beispiel bitte!

    Die Zeilen kannst du mit strcmp vergleichen. Wenn es auf Geschwindigkeit ankommt, kannst du binäres Suchen oder ein Hashverfahren implementieren.

    habe keine Ahnung was Hashverfahren ist? und mit strcmp habe ich auch schon versucht hat auch nicht geklappt, wenn du mir das genau schilderst in ein Beispiel wäre sehr nett von dir??



  • Du könntest
    - eine Zeile einlesen
    - zu ihr einen hash berechnen
    - schauen ob der hash schon in einer sortierten Liste steht (->binäre Suche)
    - wenn nicht den wert (an richtiger Stelle) einfügen und zeile in andere Datei schreiben



  • Du könntest
    - eine Zeile einlesen
    - zu ihr einen hash berechnen
    - schauen ob der hash schon in einer sortierten Liste steht (->binäre Suche)
    - wenn nicht den wert (an richtiger Stelle) einfügen und zeile in andere Datei schreiben

    ich finde dein vorschlag gut? aber wie man das in C-sprache codieren kann habe ich keine Ahnung kenne mich mit hach und binäre suche überhaupt nicht und im internet habe ich auch nichts gefunden(mit c-sprache)? wenn du mir das genauer in einem Beispiel erklärst ?danke





  • Du könntest
    - eine Zeile einlesen
    - zu ihr einen hash berechnen

    mit c geht die berechnung von Zeilen mit hash nicht oder?



  • hier gibts ein paar billige hsh-funktionen in c:
    http://www.fantasy-coders.de/projects/gh/html/x435.html



  • Hi !

    azoul schrieb:

    hat jemand eine ideee wie man das programmieren kann. ?

    Ja, ich hätte da die eine oder andere.
    Wofür brauchst du das, soll das mal in der Praxis laufen, oder ist das eine Schulaufgabe ?

    Für den ersten Fall ( bei großen Datenmengen ) würde ich eine andere Form des Speicherns wählen, bzw. eine
    ergänzende Form zur Bestehenden.
    Konkret: die Datei verkehrsdaten.txt in mehrere Dateien aufteilen.

    Die Dateinamen können dabei z.B. aus den Usernamen gebildet werden:
    user0_user1.txt. Doppelte Einträge sollen darin erst gar nicht gespeichert werden.
    Oder bilde doch die Dateinamen gleich aus der ganzen Zeile:
    A_192.168.0.84_5996_192.168.0.221_5890_0_user0_user1.txt
    Dann können erst gar keine doppelten Einträge entstehen, wenn die Existenz
    der Datei geprüft wird.
    Macht die Suche dach doppelten Einträgen schneller, ne.

    Wenns ne Schulaufgabe ist oder so, dann käme hier der Einsatz einer einfach Verketteten Liste in Frage oder char-Array-Blöcke. Die Zeilen können ja nicht nur doppelt, sonder auch drei-, vierfach usw. vorkommen.

    Mit Hashfunktionen und binärer Suche wirst du hier etwas mehr Aufwand haben, weil die Datei oder ihre Kopie dafür anders formatiert sein muss. Wäre aber auch ne gute Übung.
    Für die Hashsuche muss die maximale Anzahl der Zeilen im Voraus bekannt sein. Wird diese überschritten, so muss eine neue Datei erstellt und der ganze Kram umkopiert werden. Das ist irgendwie Käse, ne.
    Für eine binäre Suche, oder auch Halbierungssuche genannt, müsstest du die Zeilen vorher sortieren.

    Hashschlüssel bilden und danach dann binär suchen wäre allerdings, ohne jemandem zu nahe treten zu wollen, Käse hoch 7 😃 bzw. Doppelmoppelmurks.

    Das kannst du viel einfacher haben. Siehe obiger Vorschlag.

    Das mit deinen 'E-Zeilen' kapiere ich nicht so ganz, aber wenn du nur

    Gruß,
    B.B.



  • Big Brother Schrieb!

    die Datei verkehrsdaten.txt in mehrere Dateien aufteilen.

    Das Programm soll im Praxis laufen. und ist ein teil meiner Diplomarbeit
    Die Textdatei ist nicht fest, sie wird ständig von anderem Programm angehängt. wie kann ich die überhaupt in mehrere Dateien teilen??
    und das Programm soll für verschiedene IPs, PortNr und Namen funktionieren...??
    das ist das Problem bei der ganze Geschichte...

    Hat jemand noch andere idee wie das zu machen ist muss die Diplomarbeit in zwei wochen abgeben...



  • azoul schrieb:

    ... sie wird ständig von anderem Programm angehängt...

    Sind die Programme von dir ?
    Oder hast du gar keinen Einfluss darauf, wie die Daten gespeichert werden ?
    Wenn die Daten immer bloß angehängt werden dann wird die Datei irgendwann zu groß, ne.

    Vorhin ist mir bei copy/paste ein Teil verloren gegangen:
    Das mit deinen 'E-Zeilen' kapiere ich nicht so ganz, suchst du nach Zeilen die sich vorn nur durch ein E unterscheiden ?

    Wennste jetzt gar keinen Einfluss auf das Format hast dann lies doch erstmal die Datei in eine verkettete Liste ein und zwar so, das die Dublikate und deine zugeörigen E-Zeilen (was ich nicht so ganz kapiere) entfernt werden. Dann sicherst du die Dateizeigerposition, damit du den ganzen Salat nächstes mal wenn Daten dazukommen, nicht von vorn einlesen musst und speicherst deine Liste mit den Unikaten in eine andere Datei.



  • Big Brother Schrieb!

    Sind die Programme von dir ?
    Oder hast du gar keinen Einfluss darauf, wie die Daten gespeichert werden ?

    Hier das Problem vom Anfang: Habe OpenSER-Server(arbeitet als Proxy-Server), der die Daten in einer MySQL-Datenbank ablegt. Die Daten(IP-Adresse, Port-Nummer, codec und Name) sind von verschiedenen Teilnehmer, die den OpenSER-Server benutzt bzw. über ihn telefonieren. Die Daten, die in Datenbank abgelegt sind, werden von zwei verschiedene Programme ausgelesen(Die Programme werden von OpenSER_software aufgerufen sobald eine telefonat stattfindet) Ein Programm (select.c)liest die Daten(A 192.168.0.84 6066 102.168.0.221 7862 0 user user1) eine aufgebaute bzw. angefangene Telefonat, das andere programm(delete.c) liest die Daten (E 192.168.0.84 6066 102.168.0.221 7862 user user1) eine beendete Telefonat. die beide programme select.c und delete.c legen die daten in FIFO-Datei ab. danach werden von einem Programm ausgelesen und in der Textdatei Verkehrsdaten.txt angehängt. hoffe habe das problem deutlich beschrieben....

    die doppelte Einträge oder mehrfach vorkommene Einträge konnte ich vorher nicht verhindern in der Textdatei zu schreiben...



  • Hast du Email ? Dann schick ich dir mal was.
    Wenn du willst, kopiere ich das auch hier rein.
    Gruß,
    B.B.



  • Da war noch was...

    C schrieb:

    ...Die strtok Aufrufe kannst du mit einer Zeile sprintf ersetzen, macht das ganze kürzer und leserlich....

    Du meinst bestimmt sscanf.
    Guckst du hier:

    char* xxx = "E 192.168.0.84 5996 192.168.0.221 5890 0 user0 user1";
    void check_this_out()
    {
    	char AoE[8], ip1[64], ip2[64], port1[32], port2[32],
    	 codec[64], name1[64], name2[64];
    	sscanf ( xxx, "%s %s %s %s %s %s %s %s", AoE, ip1, ip2, port1, port2, codec, name1, name2 );
    	puts ( ip1 ); // usw..
    }
    


  • Big Brother Schrieb!

    Hast du Email ? Dann schick ich dir mal was.
    Wenn du willst, kopiere ich das auch hier rein.

    du kannst das auch hier rein kopieren..Danke



  • Ok, hier hast du nen Filter, der dir die Paare rausholt. Kannst du dir ja umschreiben oder so.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define MAXLINELEN 256 
    #define ANFANG 'A'
    #define ENDE 'E'
    
    void error_exit ( char* e )
    {
    	fcloseall ();
    	fprintf ( stderr, "%s\n", e );
    	exit (1);
    }
    
    int haveA ( char* A, char* file ) // Gibt es die A Zeile in der Datei 'file' ?
    {
    	FILE* fp = fopen ( file, "rt" );
    	char buf [MAXLINELEN];
    
    	if ( fp == NULL )
    		return 0; // Datei existiert( noch ) nicht, also auch nicht die Zeile.
    
    	while ( NULL != ( fgets ( buf, sizeof ( buf ), fp )))
    	{
    		if ( 0 != ferror ( fp ))
    			error_exit ( "fgets failed. " );
    
    		if ( 0 == strcmp ( A, buf ))
    		{
    			 if ( fclose ( fp ) )
    				error_exit ( "fclose failed. " );
    
    			return 1; // Zeile gefunden.
    		}
    	}
    
    	if ( fclose ( fp ) )
    		error_exit ( "fclose failed. " ); 
    
    	return 0; // Zeile nicht gefunden.
    }
    
    void addAB ( char* A, char* B, char* file ) // AE Paar zur Datei hinzufügen.
    {
    	FILE *fp = fopen ( file, "a+t" );
    
    	if ( NULL == fp ) 
    		error_exit ( "fopen failed. " );
    
    	fputs ( A, fp );
    	if ( ferror ( fp ) )
    		error_exit ( "fputs failed. " );
    
    	fputs ( B, fp );
    	if ( ferror ( fp ) )
    		error_exit ( "fputs failed. " );
    
    	if ( fclose ( fp ) )
    		error_exit ( "fclose failed. " );
    
    	return;
    }
    
    void uniquePairs ( char *Data, char* Result )
    {
    	char A [MAXLINELEN], B [MAXLINELEN];
    	FILE* fData;
    	fpos_t pos;
    
    	if ( NULL == ( fData = fopen ( Data, "rt" )))
    		error_exit ( "fopen failed. " );
    
    	while ( NULL != ( fgets ( A, sizeof ( A ), fData )))
    	{
    		if ( 0 != ferror ( fData ) )
    			error_exit ( "fgets failed. " );
    
    		if ( A [0] == ANFANG && 0 == haveA ( A, Result ))
    		{ // Zeile beginnt mit A und existiert nicht in feld.txt
    			if ( 0 != fgetpos ( fData, &pos )) // Dateizeiger sichern.
    				error_exit ( "fgetpos failed. " );
    
    			strcpy ( B, A );
    			B [0] = ENDE;
    
    			while ( NULL != ( fgets ( A, sizeof ( A ), fData )))
    			{ // Suche nach der zugehörigen E-Zeile
    
    				if ( 0 != ferror ( fData ) )
    					error_exit ( "fgets failed. " );
    
    				if ( 0 == strcmp ( A, B )) 
    				{ // Die zur A-Zeile zugehörige E-Zeile gefunden.
    					A [0] = ANFANG;
    					addAB ( A, B, Result ); // Unikat-Paar hinzufügen.
    
    					break; // Bricht die innere while-Schleife ab.
    				}
    			}
    
    			if ( 0 != fsetpos ( fData, &pos )) // Dateizeiger an gesicherte Position setzen.
    				error_exit ( "fgetpos failed. " );
    		}
    	}
    }
    
    int main()
    {
    	char *Data = "verkehrsdaten.txt";
    	char *Result = "feld.txt";
    
    	uniquePairs ( Data, Result );
    
    	return 0;
    }
    

    Gutes Gelingen.
    Gruß,
    B.B.



  • vielen Dank Big Brother ich werde es am Montag auspropieren..da es bei mir zu Hause nicht möglich ist.
    ich sage dir dann Bescheid, wenn soweit ist..
    Danke noch mal


Anmelden zum Antworten