Programm zum Auslesen/Zusammenfassen von Textfiles



  • Tehiyok schrieb:

    ... ich habe weder eine Ahnung von "strings" noch von diesen streams à la ofstream/ifstream usw.
    Die Themen die ich durch habe sind "Variablen, Schleifen, den Anfang von Funktionen und jetzt den Anfang von Arrays".

    Denkt ihr das es sinnvoll wäre jetzt einfach zu versuchen die Aufgabe zu erledigen ohne es unbedingt zu verstehen oder macht das eher wenig Sinn?

    Es macht auf jeden Fall Sinn, sich mit dem Thema 'string' und 'stream' in C++ mal zu beschäftigen. Zumindest so weit, dass Du mit obigen Code etwas anfangen kannst.
    Das sollte nicht allzu schwierig sein.

    Gruß
    Werner



  • Es macht auf jeden Fall Sinn, sich mit dem Thema 'string' und 'stream' in C++ mal zu beschäftigen. Zumindest so weit, dass Du mit obigen Code etwas anfangen kannst.
    Das sollte nicht allzu schwierig sein.

    Ich meinte nicht ob ich es generell lernen soll/muss. Meine Frage ging eher in die Richtung ob ich versuchen sollte die Aufgabe zu lösen im Schema von "Es funktioniert jetzt alles, aber ich verstehe NOCH nicht wie". Weil es wird halt schon ein wenig Zeit in Anspruch nehmen das alles zu verstehen und viel Zeit habe nicht.
    Naja ich hätte da noch eine Frage. Ich habe ja gefragt wie ich die neu erstellte Datei automatisch nach dem Datum des Tages benennen kann. Das:

    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
        std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
        std::cout << "24 hours ago, the time was "
                  << std::put_time(std::localtime(&now_c), "%F %T") << '\n';
    

    oder

    string logName = "datum LogFile "; // zum Datum s. Beitrag von SeppJ
    

    das funktioniert aber nicht. Bei dem ersten Code wird mir nur Datum und Zeit angezeigt. Beim zweiten wird die Datei "datum LogFile" genannt. Ich möchte es aber hinbekommen das jedes Mal wenn ein neues LogFile generiert wird, es als Namen das Datum dieses Tages hat. Sprich wie kann ich die Zeit automatisch einer Datei als Dateinamen zuweißen?


  • Mod

    Tehiyok schrieb:

    Ich meinte nicht ob ich es generell lernen soll/muss. Meine Frage ging eher in die Richtung ob ich versuchen sollte die Aufgabe zu lösen im Schema von "Es funktioniert jetzt alles, aber ich verstehe NOCH nicht wie". Weil es wird halt schon ein wenig Zeit in Anspruch nehmen das alles zu verstehen und viel Zeit habe nicht.

    Das ist aber extrem wichtig. Programmieren ist nicht Code aus dem Internet zusammen zu kopieren. Code ist Logik pur. Du musst genau wissen, was du tust. Du musst von jedem einzelnen Zeichen in deinem Code verstehen, wo und warum du es setzt.

    Beweis:

    Naja ich hätte da noch eine Frage. Ich habe ja gefragt wie ich die neu erstellte Datei automatisch nach dem Datum des Tages benennen kann. Das:

    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
        std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
        std::cout << "24 hours ago, the time was "
                  << std::put_time(std::localtime(&now_c), "%F %T") << '\n';
    

    oder

    string logName = "datum LogFile "; // zum Datum s. Beitrag von SeppJ
    

    das funktioniert aber nicht. Bei dem ersten Code wird mir nur Datum und Zeit angezeigt. Beim zweiten wird die Datei "datum LogFile" genannt. Ich möchte es aber hinbekommen das jedes Mal wenn ein neues LogFile generiert wird, es als Namen das Datum dieses Tages hat. Sprich wie kann ich die Zeit automatisch einer Datei als Dateinamen zuweißen?

    Was denkst du denn, was die Codes machen? Was sollte wohl der Kommentar von Werner bedeuten? Das erste ist ein Beispiel für ein ähnliches Problem und das zweite ist der Hinweis, dass du es so machen sollst wie im ersten Beispiel. Wenn du nicht einmal erkennst, das etwas ein Beispiel ist, wie willst du dann jemals eigenständig etwas programmieren können?



  • Was denkst du denn, was die Codes machen? Was sollte wohl der Kommentar von Werner bedeuten? Das erste ist ein Beispiel für ein ähnliches Problem und das zweite ist der Hinweis, dass du es so machen sollst wie im ersten Beispiel. Wenn du nicht einmal erkennst, das etwas ein Beispiel ist, wie willst du dann jemals eigenständig etwas programmieren können?

    Dazu hätte ich erwähnen sollen das ich ungefähr wusste wie ich mir die Zeit "anzeigen" lasse, ich habe lediglich keine Ahnung wie ich das als Dateiname für eine neue Datei verwende bzw. damit verbinde.
    Ich habe also sehr wohl verstanden das es nur ein Beispiel war, allerdings war das gezeigte mir schon ungefähr bekannt und das was ich wissen wollte weiß ich noch immer nicht. Und dann einen Programmieranfänger der sich nur mit besagten Dingen auskennt(Variablen, Schleifen, den Anfang von Funktionen und jetzt den Anfang von Arrays) zu fragen wie er dann jemals selbständig programmieren will finde ich etwas... naja.
    Und die Antwort auf deine Frage wäre, wenn ich mich besser auskenne. Die mir auferlegte Aufgabe übersteigt einfach mein momentanes Wissen.



  • Hallo,

    .. nur die Ruhe. Deine Frage war:

    Tehiyok schrieb:

    wie kann ich die Zeit automatisch einer Datei als Dateinamen zuweißen?

    Die führende Aussage:

    Tehiyok schrieb:

    das funktioniert aber nicht. Bei dem ersten Code wird mir nur Datum und Zeit angezeigt. Beim zweiten wird die Datei "datum LogFile" genannt.

    war in diesem Kontext etwas irreführend.

    Du kannst das Problem über einen std::ostringstream lösen. Als Anfänger kannst Du das auch nicht wissen. Sieht ungefähr so aus:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <chrono>
    #include <ctime>    // std::time_t
    #include <iomanip>  // put_time
    #include <sstream>  // ostringstream
    
    int main()
    {
        using namespace std;
        auto const maxSenkenGroesse = 10000000;  // Groesse des Output-Files in Byte
    
        int logNr = 1;      // erste Nummer für das File 'TraxisService'
        int quelleNr = 1;   // erste Nummer für die Quelldatei
    
        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
        std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
        ostringstream buffer;
        buffer << std::put_time(std::localtime(&now_c), "%Y-%m-%d %H:%M:%S"); // s. http://www.cplusplus.com/reference/ctime/strftime/
        string logName = buffer.str() + " LogFile "; // Datum davor hängen
    
        // usw. wie oben ab Zeile 13
    

    Gruß
    Werner



  • Danke für deine Hilfe Werner.
    Allerdings stehe ich jetzt vor einem noch größeren Problem, bei dem mir bisher auch niemand sagen konnte wie ich es lösen kann.

    if (number = ...)
    

    number erhöht sich in jedem Schleifendurchlauf um 1 und beginnt bei 1. Jetzt soll Folgendes passieren. Es soll jedes Mal wenn number 1, 6, 11, 16, 21, 26 usw. ist die Bedingung wahr sein. Sprich jedes 5. Mal von 1 weg soll sich die Bedingung aktivieren. Wie bekomme ich das hin? Mit einer Gleichung kann ich das nicht schaffen oder? Bei den Zahle gibt es ja ein Schema, kann ich dieses irgendwie als Bedingung in die Klammer setzen? Ich häng da grad seit 2h davor und komme nicht drauf, selbst mit google nicht.



  • Hallo,

    Tehiyok schrieb:

    number erhöht sich in jedem Schleifendurchlauf um 1 und beginnt bei 1. Jetzt soll Folgendes passieren. Es soll jedes Mal wenn number 1, 6, 11, 16, 21, 26 usw. ist die Bedingung wahr sein. Sprich jedes 5. Mal von 1 weg soll sich die Bedingung aktivieren. Wie bekomme ich das hin? Mit einer Gleichung kann ich das nicht schaffen oder?

    doch sicher!
    ich kenne Deine Schulbildung nicht. Hast Du schon mal was vom Modulo gehört?

    Die entsprechende Funktion bzw. der Operator in C++ ist das '%'-Zeichen. Etwa so:

    if( (number % 5) == 1 ) // '==' dient zum Vergleich; '=' wäre eine Zuweisung!
        {   // number hat jetzt einen Wert von {1, 6, 11, 16, 21, ...}
            // usw. Bedingung ist eingetreten
    

    Tehiyok schrieb:

    ... bei dem mir bisher auch niemand sagen konnte wie ich es lösen kann.

    erstaunlich!

    Gruß
    Werner

    PS.:

    Tehiyok schrieb:

    ... und komme nicht drauf, selbst mit google nicht.

    Denken ist wie googeln; nur krasser!



  • Vielen lieben Dank für deine Hilfe Werner!
    Ich habe in meiner Schulausbildung noch nie Modulo verwendet. Allerdings bin ich bei meinem Selbststudium darauf gestoßen. Ich habe aber nicht ganz verstanden für was bzw. welche Verwendungszwecke es hat. Jetzt weiß ich es! 🙂



  • Hallo,

    ich hätte da ein weiteres Problem.

    ifstream Quelldatei;
             Quelldatei.open("../../Log Files/TraxisService.log."[number], ios_base::in);
    

    Folgendes Problem. Diese LogFiles heißen "TraxisService.log.1" "TraxisService.log.2" usw. Pro Durchlauf der Schleife soll der Inhalt eines dieser Files ausgelesen und in ein anderes/neues kopiert werden. Ich dachte das ich das mit obigem Code hinkriege in dem ich eine Variable dahinter setzte und diese pro Durchlauf um eines hochzähle. Das funktioniert natürlich nicht. Habe ich einfach etwas falsch geschrieben oder ist der Denkansatz schon falsch?


  • Mod

    Tehiyok schrieb:

    Habe ich einfach etwas falsch geschrieben oder ist der Denkansatz schon falsch?

    Letzteres. Du hast offensichtlich 0 aus diesem Thread gelernt.



  • Letzteres. Du hast offensichtlich 0 aus diesem Thread gelernt.

    Ich weiß nicht warum deine Antworten immer so offensiv sein müssen? Ich meine gesagt zu haben das ich Anfänger bin und mich nicht gut auskenne. Und doch ich habe schon etwas aus den Antworten hier gelernt. Anscheinend aber nicht das was mir hier weiterhilft.
    Und wieso antwortest du mir überhaupt wenn das alles ist was du zu sagen hast? Das ist weder hilfreich noch produktiv.


  • Mod

    Tehiyok schrieb:

    Letzteres. Du hast offensichtlich 0 aus diesem Thread gelernt.

    Ich weiß nicht warum deine Antworten immer so offensiv sein müssen?

    Sieh den verschärften Ton als Rückmeldung an, nicht nur von mir, sondern von allen anderen Helfern auch. Wie du vielleicht bemerkst, waren die ersten Beiträge nett und hilfsbereit. Aber da sie auf taube Ohren stießen, sind diejenigen, die dir geholfen haben, enttäuscht über die vergebene Mühe. Ich bin bloß der einzige, der dir nun noch antwortet.

    Dein neues Problem ist exakt das gleiche wie gehabt. Aber da du nur blind unsere Lösungen übernommen hast (weshalb ich vermieden habe, dir eine direkt übernehmbare Lösung zu geben, aber ich konnte Werner nicht aufhalten), ohne zu versuchen, diese zu verstehen, kannst du nun nicht die nötige Transferarbeit leisten und diese Lösung nicht auf das neue, identische Problem anwenden.



  • Dann darf ich annehmen das das auch mit strings zu lösen ist?


  • Mod

    Tehiyok schrieb:

    Dann darf ich annehmen das das auch mit strings zu lösen ist?

    Strings und/oder Stringstreams, denn du möchtest schließlich eine Zeichenkette (=String) mit passendem Inhalt erzeugen.

    Ganz am Anfang dieses Threads wurde das alles schon vorhergesagt:

    SeppJ schrieb:

    Wenn die Dateinamen veränderlich sein müssen, dann musst du eben eine veränderliche Zeichenkette als Dateiname benutzen. Von std::string hast du sicher schon gehört? Mit std::to_string kann man Zahlen in std::string umwandeln und sich dann etwas basteln. Oder wenn man komplexere Bastelaufgaben hat, gibt es auch noch std::stringstream, das ist wieder ein Stream, mit dem gleichen Interface das du schon kennst, bloß dass im Hintergrund ein std::string als Quelle/Ziel steht, den du dir nach der Bastelei über die str() Funktion holen kannst.



  • Gut, danke für die Hilfe.



  • Hallo Tehiyok,

    Tehiyok schrieb:

    ich hätte da ein weiteres Problem.

    ifstream Quelldatei;
             Quelldatei.open("../../Log Files/TraxisService.log."[number], ios_base::in);
    

    Folgendes Problem. Diese LogFiles heißen "TraxisService.log.1" "TraxisService.log.2" usw. Pro Durchlauf der Schleife soll der Inhalt eines dieser Files ausgelesen und in ein anderes/neues kopiert werden. Ich dachte das ich das mit obigem Code hinkriege in dem ich eine Variable dahinter setzte und diese pro Durchlauf um eines hochzähle. Das funktioniert natürlich nicht. Habe ich einfach etwas falsch geschrieben oder ist der Denkansatz schon falsch?

    Ich kann SeppJ schon verstehen. Du solltest Dir den ganzen Tread noch mal in Ruhe durchlesen. Ich verstehe aber auch Dich - als Programmieranfänger hast Du natürlich etliche Information nicht, die SeppJ und ich hier implizit voraussetzen.
    Die Antwort auf Deine Frage steht weiter oben in meinem Beitrag von 21:19:54 09.02.2016 in dem Listing in Zeile 18.

    Weiter steht da auch

    Werner Salomon schrieb:

    Im Prinzip kannst Du folgendes machen:

    ifstream Quelldatei("../../Log Files/TraxisService.log.[number]"); // das ios_base::in kann man sich schenken (i)fstream ohne 'in' geht nicht
    

    das ' ios_base::in ' brauchst Du wirklich nicht. Und das " [number] " ist nur ein Platzhalter für eben die Zahl, die dann dahin kommt.

    Weiter darfst Du nicht den Fehler machen, die Variable 'Quelldatei' außerhalb der Schleife zu definieren und dann in der Schleife wiederholt zu öffnen. Bin mir nicht sicher, ob das funktioniert - Du liegst jedenfalls auf der sicheren Seite, wenn 'Quelldatei' nur innerhalb der Schleife existiert. Und bitte mach' Dir keine Gedanken ob das 'nicht performant' wäre. Den Unterschied kann man wahrscheinlich gar nicht messen.

    Gruß
    Werner



  • Vorab danke für eure Beiträge. Ich habe das nun mit den strings versucht, aber anscheinend etwas falsch gemacht.

    string string1, string2, string3;
    	ostringstream stringnumber;
    	int number = 1;
    
    	stringnumber << number;
    	string2 = stringnumber.str();
    	string1 = "../../Log Files/TraxisService.log.";
    	string3 = string1 + string2;
    
    	do
    	{
    		ifstream Quelldatei;                                                     
    		  Quelldatei.open(string3, ios_base::in);
    
    		   if (!Quelldatei)                                                                
    		   {
    				cerr << "Eingabe-Datei kann nicht geoeffnet werden\n";
    		   }
    

    Da wäre jetzt mal meine erste Frage inwiefern ich das "ios_base::in" weglassen kann. Soll bzw. kann ich das dann auch so machen:

    ifstream Quelldatei;                                                     
              Quelldatei.open(string3);
    

    Meine zweite Frage wäre was ich bei den strings falsch gemacht habe. Wenn ich mir vor der "do" Schleife über cout den Inhalt von string3 couten lasse wird mir eigentlich genau das ausgespuckt was ich brauche. Daher vermute ich das ich hier etwas falsch gemacht habe:

    Quelldatei.open(string3, ios_base::in);".
    

    Habe ich da irgendwas vergessen?

    Edit: Meintest du mit Quelldatei außerhalb der Schleife, außerhalb der if-Schleife? Falls ja, das hat eigentlich funktioniert als ich es getestet habe.


  • Mod

    Tehiyok schrieb:

    Meine zweite Frage wäre was ich bei den strings falsch gemacht habe. Wenn ich mir vor der "do" Schleife über cout den Inhalt von string3 couten lasse wird mir eigentlich genau das ausgespuckt was ich brauche. Daher vermute ich das ich hier etwas falsch gemacht habe:

    Dann wird wohl schlicht deine Annahme nicht stimmen, was der korrekte Dateiname ist. An sich ist der Code korrekt. Da du einen relativen Pfad benutzt, stell sicher, dass dein Arbeitsverzeichnis auch wirklich das ist, was du denkst. Testhalber kannst du erst einmal einen absoluten Pfad benutzen. Dann die Datei ins vermeintliche Arbeitsverzeichnis kopieren und testen, ob sie dort geöffnet wird.

    Eventuell könnte es auf irgendwelchen komischen Systemen Probleme mit Leerzeichen im Pfad geben. Sollte nicht so sein, aber ich will es auch nicht absolut als Ursache ausschließen.

    Da wäre jetzt mal meine erste Frage inwiefern ich das "ios_base::in" weglassen kann.

    "ios_base::in" ist sowieso schon Defaultmodus für ifstreams und somit redundant. Ebenso mit out für ofstreams. Überhaupt kannst du dir das open auch ganz sparen und das Objekt sofort passend erzeugen:

    ifstream Quelldatei(string3);
    

    Edit: Meintest du mit Quelldatei außerhalb der Schleife, außerhalb der if-Schleife? Falls ja, das hat eigentlich funktioniert als ich es getestet habe.

    www.if-schleife.de

    Er meint, du sollst den ifstream in Zeile 9 erzeugen, vor dem do. Das Öffnen von Dateien ist eine sehr zeitaufwändige Aktion und sollte daher möglichst nur einmal durchgeführt werden. Ich weiß, dass dir hier (korrekterweise) empfohlen wurde, erst einmal nicht auf Performance zu achten, aber Öffnen und Schließen von Dateien sind so krass langsam, da sollte man eine Ausnahme machen.



  • Hallo, melde mich jetzt seit einiger Zeit Mal wieder, hatte in den vergangener Tagen nur sehr wenig Zeit mich mit meinem Programm zu befassen.
    Ich habe dank euch das Problem mit dem öffnen der Datei lösen können und hänge jetzt allerdings dabei, eine neue Datei zu öffnen/erstellen die nach dem aktuellen Datum benannt wird.

    time_t time = std::time(0);
        string s = std::ctime(&time);
    
    	cout << s;
    

    Ich habe jetzt im string s (ja mir ist bewusst das man einen string nicht einfach s nennen soll, mache ich dann im fertigen Programm auch nicht) genau das was ich brauche: Wed March 02 09:46:58 2016. Wenn ich jetzt aber:

    ofstream Zieldatei (s);
    

    eingebe wird gar keine Datei erstellt. Was habe ich falsch gemacht? Passt irgendwas mit dem Format des Datums nicht?



  • Deinem Lieblings-OS bzw. -Dateisystem werden wohl keine Doppelpunkte im Dateinamen schmecken. Ah, und ein newline ist auch drin.


Anmelden zum Antworten