TXT Datei durchsuchen und Leseposition setzen



  • Hallo zusammen.
    Heute habe ich ein hoffentlich etwas einfacher zu lösendes Problem.
    Ich habe ein Template geschrieben, dass bisher nur den Zweck hat Daten, die es von einer Funktion bekommt ans Ende der Datei zu hängen.

    Jeder dieser "Datensätze" beginnt hierbei mit dem string "==BEGIN OF 1==" und endet mit "==END OF 1==". (Hier vielleicht auch die Frage, wie ich hier in der zuweisung string beginSchreiber = "==BEGIN OF 1=="; die 1 durch eine int Variable ersetzen kann?).

    Das sieht dann z.B. so aus

    ==BEGIN OF 1==
    test text 1
    test text 2
    etc.
    ==END OF 1==
    

    Ich hätte nun gerne, dass der Lesezeiger in einer anderen Funktion nach eben diesem "==BEGIN OF 1==" sucht und den Zeiger auf die Zeile darunter (also im Beispiel "test text 1") setzt.

    Gibt es eine Zeigerfunktion, mit der ich den Zeiger beispielsweise direkt in Zeile 5 (also nicht Position 5) setzen kann ?

    Und vielleicht noch als abschließende Frage:
    Immer ans Ende der Datei zu schreiben ist ja nicht die feine Art. Kann ich irgendwie auch den Schreibzeiger in ZEILE x setzen ?

    Hoffe ihr könnt mir etwas weiterhelfen 😉

    Guten Start in die Woche !
    Jörg



  • JörgK schrieb:

    Hallo zusammen.
    Heute habe ich ein hoffentlich etwas einfacher zu lösendes Problem.
    Ich habe ein Template geschrieben, dass bisher nur den Zweck hat Daten, die es von einer Funktion bekommt ans Ende der Datei zu hängen.

    Jeder dieser "Datensätze" beginnt hierbei mit dem string "==BEGIN OF 1==" und endet mit "==END OF 1==". (Hier vielleicht auch die Frage, wie ich hier in der zuweisung string beginSchreiber = "==BEGIN OF 1=="; die 1 durch eine int Variable ersetzen kann?).

    Ja, schau dir mal den Operator << an.

    Das sieht dann z.B. so aus

    ==BEGIN OF 1==
    test text 1
    test text 2
    etc.
    ==END OF 1==
    

    Ich hätte nun gerne, dass der Lesezeiger in einer anderen Funktion nach eben diesem "==BEGIN OF 1==" sucht und den Zeiger auf die Zeile darunter (also im Beispiel "test text 1") setzt.

    Ich verstehe nicht ganz, was die Austauschbarkeit der 1 dann bewirken soll. Warum sollte ich einen Datensatz rüberschieben, wenn ich gleichzeitig die Information mitgebe, dass die Hälfte eh nicht zu gebrauchen ist (im Beispiel z.B. ==BEGIN OF 2==)

    Nachdem Du nun deine Startzeilennummer so wunderbar in einen string geballert hast, muss die Funktion, die den Datensatz bearbeitet, ihn erstmal wieder rausfriemeln. Hier würde ich Dir sehr empfehlen, Dir anzuschauen, was man mit strings so alles machen kann, wie man darin was suchen kann, die zerlegen kann, etc.

    Gibt es eine Zeigerfunktion, mit der ich den Zeiger beispielsweise direkt in Zeile 5 (also nicht Position 5) setzen kann ?

    Ja, jenachdem ob du mit C Handles oder C++ Handles arbeitest, sogar verschiedene. Siehe google, oder cplusplus.com, diese ganzen standard funktionen sind da 1a dokumentiert.

    Und vielleicht noch als abschließende Frage:
    Immer ans Ende der Datei zu schreiben ist ja nicht die feine Art. Kann ich irgendwie auch den Schreibzeiger in ZEILE x setzen ?

    Aber sicher, nichts ist unmöglich 🙂


  • Mod

    JörgK schrieb:

    Gibt es eine Zeigerfunktion, mit der ich den Zeiger beispielsweise direkt in Zeile 5 (also nicht Position 5) setzen kann ?

    Eine Datei ist eine lange Folge von Bytes. Die Interpretation, dass ein bestimmtes dieser Bytes einen Zeilenumbruch bedeutet ist menschlich. Du musst irgendwie die Anzahl dieser Zeichen zählen, wenn du wissen möçhtest, in welcher Zeile du bist.

    Beim Lesen ist es übrigens bei nicht zu großen Dateien (d.h. ein paar hundert MB und kleiner) durchaus üblich, die Datei einfach komplett einzulesen. Dann kannst du sie auch gleich zeilenweise in einer passenden Datenstruktur (z.B. vector<string>) speichern und kannst dann nach Herzenslust zeilenweise da drin rumspringen.

    Immer ans Ende der Datei zu schreiben ist ja nicht die feine Art. Kann ich irgendwie auch den Schreibzeiger in ZEILE x setzen ?

    Ja. Aber erwarte nicht, dass da eingefügt wird. Es wird überschrieben. Wenn du einfügen willst, dann lies, wie oben angedeutet, in geeignete Datenstrukturen ein, mach die Änderungen und schreib alles wieder raus.



  • Hi,

    du kannst dir z.B. eine solche Funktion schreiben:

    std::istream& set_to(std::istream&, size_t, size_t = 0);      //row = Zeile, ch = Zeichen Nr.
    std::istream& set_to(std::istream& is, size_t row, size_t ch)
    {
        is.seekg(0, std::ios::beg);//Setze Lesezeiger auf Anfang der Datei
        while(row--)
            is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//In Schleife soundso viele Zeilen überspringen.
        is.ignore(ch, '\n');//Soundso viele Zeichen ignorieren
        return is;//Rückgabe einer Referenz auf istream-Objekt
    }
    

    Ausschlaggebend ist die istream::ignore() Funktion.

    🕶



  • Hobo schrieb:

    Ich verstehe nicht ganz, was die Austauschbarkeit der 1 dann bewirken soll. Warum sollte ich einen Datensatz rüberschieben, wenn ich gleichzeitig die Information mitgebe, dass die Hälfte eh nicht zu gebrauchen ist (im Beispiel z.B. ==BEGIN OF 2==)

    Nachdem Du nun deine Startzeilennummer so wunderbar in einen string geballert hast, muss die Funktion, die den Datensatz bearbeitet, ihn erstmal wieder rausfriemeln. Hier würde ich Dir sehr empfehlen, Dir anzuschauen, was man mit strings so alles machen kann, wie man darin was suchen kann, die zerlegen kann, etc.

    Das ganze hat den Sinn, dass ich ein Array von einer bestimmten Klasse habe.
    Die Eigenschaften der einzelnen Objekte wollte ich aber auch gerne behalten, wenn ich das Programm beende. Daher hatte ich mir gedacht, dass ich für jede Stelle des Arrays einen kleinen Datensatz in eine Datei schreibe und bei Bedarf wieder auslese.

    Ja, jenachdem ob du mit C Handles oder C++ Handles arbeitest, sogar verschiedene. Siehe google, oder cplusplus.com, diese ganzen standard funktionen sind da 1a dokumentiert.

    Ich arbeite mit C++. Aber leider ist alles was ich gefunden habe, wie ich den Zeiger an eine bestimmt Stelle innerhalb einer Zeile setze (seekp, seekg), aber nicht, wie ich ihn in eine bestimmt Zeile setze.

    Und vielleicht noch als abschließende Frage:
    Immer ans Ende der Datei zu schreiben ist ja nicht die feine Art. Kann ich irgendwie auch den Schreibzeiger in ZEILE x setzen ?

    Aber sicher, nichts ist unmöglich 🙂

    Und würdest du mir den Befehl dafür auch verraten 😉

    Immer ans Ende der Datei zu schreiben ist ja nicht die feine Art. Kann ich irgendwie auch den Schreibzeiger in ZEILE x setzen ?

    Ja. Aber erwarte nicht, dass da eingefügt wird. Es wird überschrieben. Wenn du einfügen willst, dann lies, wie oben angedeutet, in geeignete Datenstrukturen ein, mach die Änderungen und schreib alles wieder raus.

    Das ist genau das, was ich suche 🙂
    Ich möchte, wenn das Array sich ändert natürlich auch die Datei ändern - altes SOLL da wegfallen 😉

    Gruß Jörg


  • Mod

    JörgK schrieb:

    Ich möchte, wenn das Array sich ändert natürlich auch die Datei ändern - altes SOLL da wegfallen 😉

    Fein, dann einfach Datei zum Lesen und zum Schreiben öffnen (ios::out | ios::in) und du kannst den Schreibzeiger munter an jede Stelle der Datei schieben.

    Aber nur um das nochmal klar zu stellen, weil viele Anfänger das trotz mehrfacher Warnung nicht verstehen: Datei heißt einfach nur Bytefolge, nix Formatierung. Das heißt zum Beispiel, wenn in der Datei steht:

    Name: Hans
    Straße: Musterstraße
    

    und du änderst "Hans" durch überschreiben in "Johannes", dann wird in der Datei hinterher

    Name: Johannesaße: Musterstraße
    

    stehen.



  • Hallo Sepp,
    ich hab das gerade noch mal so ausprobiert mit dem ersetzen, wie du das gezeigt hast, aber irgendwie löscht der mir dabei immer die ganze Zeile.
    Hier mal mein Code:

    template <class X> void dateischreiber (X datensatz, int zeigerPosition) {
        ofstream songstream ("Song.txt");
        songstream.seekp (zeigerPosition, ios::beg);
            if (songstream.good()) {
            songstream << datensatz;
            } else {
                //Fehlermeldung einfügen
            }
            songstream.close();
    }
    

    Lasse ich jetzt einen Char-Array mit 100 Stellen an position 0 schreiben, funktioniert das soweit erstmal. Lasse ich dann aber an Stelle 102 (oder höher) einen anderen Char-Array oder Int oder sonst was schreiben, ist nur noch der neue Text in der Datei und der alte verschwindet komplett.

    Wo ist da mein Denkfehler?

    Gruß


  • Mod

    Wenn du einen ofstream öffnest, dann ist standardmäßig ios::out der Openmode. Dies löscht eine vorher vorhandene Datei. Du musst daher, wie gesagt, ios::out | ios::in als Openmode nehmen.



  • SeppJ schrieb:

    Dies löscht eine vorher vorhandene Datei.

    Was? Du meinst std::ios::trunc. Seit wann löscht std::ios::out?


  • Mod

    Hacker schrieb:

    Was? Du meinst std::ios::trunc. Seit wann löscht std::ios::out?

    Seit 1979. Oder da dieses Verhalten auf den Openmodes von C basiert eigentlich seit 1972. Und da diese wiederum auf B basieren...



  • SeppJ schrieb:

    Wenn du einen ofstream öffnest, dann ist standardmäßig ios::out der Openmode. Dies löscht eine vorher vorhandene Datei. Du musst daher, wie gesagt, ios::out | ios::in als Openmode nehmen.

    Vielen herzlichen Dank !
    Daran hat's gelegen. Mein Buch hat diese vorgehensweise dummerweise mit folgenden Worten beschrieben:

    Wenn Sie beides tun wollen [Anm. gemeint ist schreiben und lesen], benutzen Sie fstream und setzen den mode auf in|out - und viel Glück dabei, es ist häufig einfacher eine Datei erst komplett zu schreiben [...] ,als alles gleichzeitig zu tun.

    Naja. Nun weiß ich's ja. Vielen Dank nochmal 😉

    Gruß Jörg


  • Mod

    JörgK schrieb:

    Daran hat's gelegen. Mein Buch hat diese vorgehensweise dummerweise mit folgenden Worten beschrieben:

    Wenn Sie beides tun wollen [Anm. gemeint ist schreiben und lesen], benutzen Sie fstream und setzen den mode auf in|out - und viel Glück dabei, es ist häufig einfacher eine Datei erst komplett zu schreiben [...] ,als alles gleichzeitig zu tun.

    Hmm, dieser lockere Stil...Das Buch ist aber nicht von Jürgen Wolf, oder?



  • SeppJ schrieb:

    Hmm, dieser lockere Stil...Das Buch ist aber nicht von Jürgen Wolf, oder?

    Dieser Stil könnte vom Großadministrator höchstpersönlich sein, denn eine kurze Google-Recherche nach dem Zitat brachte C++ für Dummies zum Vorschein.


  • Mod

    😕 Hat der Großadministrator die deutsche Ausgabe geschrieben? War mir bisher gar nicht bekannt.





  • Na schau, da GRÖADAZ 😃


Log in to reply