Problem mit fstream



  • Hallo,

    ich habe 3 Funktionen geschrieben, mit der man Dateien "komfortabler" lesen bzw. ändern kann.
    Meine letzte Funktion, mit der man eine Zeile aus einer Datei löschen kann, funktioniert allerdings nicht richtig. Statt eine Zeile zu löschen, leert diese die ganze Datei.
    Meine Frage: Wo liegt der Fehler?

    void del_line (string file,long long int line) {
    		/*	Löscht eine Zeile von einer externen Datei.
    			Parameter [0] => Pfad zu der zu bearbeitenden Datei
    			Parameter [1] => die Zeile, die gelöscht werden soll
    			Rückgabewert: [void]
    		*/
    		string tbuffer_0;
    		tbuffer_0 = "";
    		string tbuffer_1;
    		tbuffer_1 = "";
    		long long int counter;
    		counter = 0;
    		bool fertig;
    		fstream fs;
    		fs.open (file.c_str (),fstream::in | fstream::out | fstream::trunc);
    		fertig = fs.eof ();
    		while ((fertig == false)) {
    			getline (fs,tbuffer_0);
    			if ((counter != line)) {
    				tbuffer_1 += tbuffer_0 + "\n";
    			};
    			counter += 1;
    			fertig = fs.eof ();
    		};
    		fs << tbuffer_1.c_str ();
    	};
    

    Danke im Voraus!

    MfG

    Seikuassi



  • Was macht fstream::trunc?



  • ...



  • // Includes
    #include <iostream> // std::cout
    #include <string>   // std::string, std::getline
    #include <fstream>  // std::fstream
    
    // Discard need of prepend std::
    using namespace std;
    
    // Delete one file line
    bool del_line(string filename, long long int line){
        // Open file in read mode
        fstream file(filename, ios_base::in);
        if(!file)
            return false;
        // Text buffers
        string line_buffer, file_buffer;
        // Line counter
        long long int counter = 0;
        // Marker of line deletion
        bool line_deleted;
        // Read lines except not wished one
        while(getline(file, line_buffer))
            if(counter++ == line)
                line_deleted = true;
            else
                file_buffer += line_buffer + '\n';
        // Remove last newline
        if(file_buffer.size() > 0)
            file_buffer.erase(file_buffer.size() - 1);
        // Deleted one line?
        if(!line_deleted)
            return false;
        // Reopen file in write mode without content
        file.close();
        file.open(filename, ios_base::out | ios_base::trunc);
        if(!file)
            return false;
        // Write new content to file
        file << file_buffer;
        // Everything done!
        return true;
    }
    
    // Program entry
    int main(){
        // Could delete first line of file "input.txt"?
        if(del_line("input.txt", 0))
            cout << "Success!";
        else
            cout << "Failed!";
    }
    


  • Hallo,

    Was macht fstream::trunc?

    "trunc" (aus dem Englischen truncate = kürzen) bedeutet, dass der Inhalt einer z.B. Datei ersetzt werden soll.
    "app" hingegen hängt dagegen den neuen Inhalt an die Datei an.

    Hier nun meine aktuelle Version, die funktioniert:

    void del_line (string file,long long int line) {
    		/*	Löscht eine Zeile von einer externen Datei.
    			Parameter [0] => Pfad zu der Datei mit der zu löschenden Zile
    			Parameter [1] => Zeile, die gelöscht werden soll
    			Rückgabewert: [NONE]
    		*/
    		string tbuffer_0;
    		tbuffer_0 = "";
    		string tbuffer_1;
    		tbuffer_1 = "";
    		long long int counter;
    		counter = 0;
    		bool fertig;
    		fstream fs;
    		fs.open (file.c_str (),ios::in); // kein "ios::trunc" !!!
    		fertig = fs.eof ();
    		if ((line > 0)) {
    			while ((fertig == false)) {
    				counter += 1;
    				getline (fs,tbuffer_0);
    				if ((counter != line)) {
    					tbuffer_1 += tbuffer_0 + "\n";
    				};
    				fertig = fs.eof ();
    			};
    			fs.close ();
    			fs.open (file.c_str (),ios::in | ios::out | ios::trunc);
    			fs << tbuffer_1;
    			fs.close ();
    		};
    	};
    

    @Swordfish:
    Ihr habt zwar alle mehr Erfahrung als ich, aber in deiner Funktion öffnest du die Datei gleich mit "ios:trunc" auf. Hast du deine Funktion getestet?
    Meiner Meinung nach löscht du beim Aufrufen des Befehles die komplette Datei.
    Das war bei mir am Anfang auch mein Fehler. Ich habe mich gefragt, warum das am Anfang nicht ging. Bis ich dann eben bemerkt habe, dass ich die Datei zuerst nur mit "ios::in" aufrufen darf, um diese zu verarbeiten und dann erst die Datei überschreiben (mit eben "ios::trunc") darf.

    Danke nochmal für eure Ideen. Haben mir weitergeholfen.

    MfG

    Seikuassi

    P.S.: Oh nein! Jetzt habe ich zu wenig Semikolone gsetzt 😃 .



  • Hallo nochmal!

    Ich habe doch noch gerade ein Fehler entdeckt:
    Wenn ich eine Zeile lösche, dann wird das Escape-Zeichen "newline" (\n) nicht entfernt. Das heißt, dass die Zeile zwar keinen Inhalt mehr hat, aber diese trotzdem noch existiert.
    Wie kann ich nun das Escape-Zeichen mit entfernen?

    Danke im Voraus!



  • Hallo nochmal nochmal 🙂 !

    Ignoriert meinen gerade geschriebenen Beitrag. Ich bekomme immer nur am Ende der Datei eine leere Zeile.
    Wie kann ich aber diese leere Zeile löschen, also den letzten "newline" (\n) entfernen.

    So ist es jetzt:

    [b]1:[/b] Hallo, das ist ein Test!
    [b]2:[/b] Und noch ein Test!
    [b]3:[/b] Und noch ein Test!
    [b]4:[/b] Und noch ein Test!
    [b]5:[/b]
    

    Und ich möchte folgendes haben:

    [b]1:[/b] Hallo, das ist ein Test!
    [b]2:[/b] Und noch ein Test!
    [b]3:[/b] Und noch ein Test!
    [b]4:[/b] Und noch ein Test!
    

    Hier noch mal meine aktuelle Funktion:

    void del_line (string file,long long int line) {
    		/*	Löscht eine Zeile von einer externen Datei.
    			Parameter [0] => Pfad zu der Datei mit der zu löschenden Zeile
    			Parameter [1] => Zeile, die gelöscht werden soll
    			Rückgabewert: [void]
    		*/
    		string tbuffer_0;
    		tbuffer_0 = "";
    		string tbuffer_1;
    		tbuffer_1 = "";
    		long long int counter;
    		counter = 0;
    		bool fertig;
    		fstream fs;
    		fs.open (file.c_str (),ios::in);
    		fertig = fs.eof ();
    		if ((line > 0)) {
    			while ((fertig == false)) {
    				counter += 1;
    				getline (fs,tbuffer_0);
    				if ((counter != line)) {
    					tbuffer_1 += tbuffer_0 + "\n"; // das müsste den Fehler hervorgerufen haben durch \n am Ende
    				};
    				fertig = fs.eof ();
    			};
    			fs.close ();
    			fs.open (file.c_str (),ios::in | ios::out | ios::trunc);
    			fs << tbuffer_1;
    		};
    		fs.close ();
    	};
    

    Danke im Voraus!

    MfG

    Seikuassi



  • Murks.



  • Lies doch die ganze Datei in einen string ein (insofern die Datei nicht übergroß ist).
    Dann suchst du nach den "\n", bis du beim x. "\n" angekommen bist, wobei x die Zeilennummer, die zu löschen ist, ist.
    Ab da kannst du dann alles bis zum x-1. "\n" löschen (du kannst ja die einzelnen Chars vom string ansprechen).
    Dann kannst du dir auch sicher sein, dass das \n weg ist.
    Und zu guter Letzt schreibst du den abgeänderten string in ein leeres File.

    Tadaa!

    Ich hoffe, dass ich dir helfen konnte und nicht zu viel vorgesagt habe 🙂

    ps.
    Deinen Code kannst um einiges kürzer und somit übersichtlicher machen:
    vorher:

    string tbuffer_0;
            tbuffer_0 = "";
            string tbuffer_1;
            tbuffer_1 = "";
            long long int counter;
            counter = 0;
            bool fertig;
            fstream fs;
            fs.open (file.c_str (),ios::in);
    

    nachher:

    string tbuffer_0 = ""; oder string tbuffer_0("");
         string tbuffer_1 = "";
         long long int counter = 0;
         bool fertig;
         fstream fs(file.c_str (),ios::in);
    


  • Ich hatte dir doch eine Lösung geschrieben, kommentiert und effektiv. Lies dir den 4ten Post nochmal durch.



  • @Youka

    Danke! Hab deinen Post erst später gelesen. Deine Funktion funktioniert prima!
    Danke für die Hilfe!

    MfG

    Seikuassi


Anmelden zum Antworten