fstream und Dateipfade



  • Hallo zusammen,

    ich habe das Problem, dass wenn ich mit fstream Arbeite zwar Dateinamen problemlos eingeben kann, aber bei Dateipfaden Probleme bekomme.

    Vorerst das System:
    Betriebssystem: Linux
    Compiler: g++

    Also ich habe eine Klasse ExampleDocument

    class ExampleDocument {
    	private:
    		char* path;		
    		string inputfile;
    		string outputfile;
    
    	public:		
    		ExampleDocument();
    		ExampleDocument(bool newdocument, bool typeInput);
    		ExampleDocument(string path, bool newdocument, bool typeInput);
    		virtual ~ExampleDocument();
    
    		int WriteDocument(string textvalue);
    };
    

    Die Methode "WriteDocument" funktioniert im ersten Durchlauf, im zweiten und in weiteren Durchläufen wird die Variable "path" verändert.

    Die Methode WriteDocument:

    int ExampleDocument::WriteDocument(string textvalue){
    	fstream f;
    
    	cout << "Pfad1: " << this->path << endl;	
    
    	f.open(this->path, ios::app|ios::out);
    	f << textvalue << endl;
    	f.close();
    
    	cout << "Pfad2: " << this->path << endl;
    
    	return 0;
    }
    

    Der Verwendete Konstruktor:

    ExampleDocument::ExampleDocument(string tmp_path, bool newdocument, bool typeInput) {
    	this->inputfile="inputFile.dat";
    	this->outputfile="outputFile.dat";
    	string file;
    	string tmp_string;
    
    	if(typeInput){
    		file = this->inputfile;
    	}else{
    		file = this->outputfile;	
    	}
    
    	tmp_string = tmp_path+file;
    
    	this->path = const_cast<char*>(tmp_string.c_str());
    
    	if(newdocument){
    		fstream fs(this->path, ios::out);
    		fs.close();	
    	}
    }
    

    Die "path" Variable wird direkt nach dem Schreiben in die Datei verändert.
    Die Ausgabe lautet:
    Pfad1: /home/einVerzeichnis/eineDatei.dat (korrekt)
    Pfad2: /home/einVerzeichnis/eineDatei.dat0 (falsch)

    Vielen Dank!

    Gruß

    mustino



  • mustino schrieb:

    ...

    class ExampleDocument {
    	private:
    		char* path;
    

    Warum nicht string ?

    mustino schrieb:

    ...

    f.open(this->path, ios::app|ios::out);
    

    Das würde ich nicht machen, weil man nunmal keine "Pfade öffnen" kann, sondern nur Files (heißt ja fstream und nicht pstream 😉 ).
    Ob das die Ursache für das Problem ist, weiß ich nicht, weil ich nicht sehe, wie die Klasse benutzt wird. Aber es sieht mir "gefährlich" aus...

    Gruß,

    Simon2.



  • Hi,

    danke vorerst fü die schnelle Antwort.

    Gibt es denn eine andere Möglichkeit eine Datei mit Pfadangabe zu öffnen und zu beschreiben???

    Gruß,

    mustino



  • ExampleDocument::ExampleDocument(std::string const& path, bool newdoc, bool type) : inputfile("inputFile.dat"), outputfile("outputFile.dat")
    {
        std::string tmp(path);
        tmp += (type == true ? inputfile : outputfile);
    
        this->path = new char[tmp.length() + 1];
        std::strcpy(this->path, tmp.c_str());
    
        if (newdoc)
            std::ofstream file_stream(this->path);
    }
    
    ExampleDocument::~ExampleDocument()
    {
        delete [] path;
    }
    

    ...



  • @Simon: Nee das ist nicht das Problem 😃 Er macht sehr viel Scheiße in 10 Zeilen-Code ... das ist das Problem 😃 Er legt ein temporäres Objekt vom Type std::string an. Holt sich dann einen const. char-Zeiger von diesem Objekt (und castet das verdammte const. auchnoch weg!!! ?! ). Dann verlässt er den Konstruktor. Das temporäre Objekt wird freigegeben. Der Zeiger zeigt sonnst wo hin 😉 Und damit auch sein this->path, denn er hat nicht den Inhalt des char-Arrays kopiert sondern nur den Zeiger umgelenkt 😃



  • Hi,

    danke für die Hilfe (die war lehrreich!). Das ich nur den Zeiger umgelenkt und nicht den Inhalt kopiert habe, darauf hätte ich kommen müssen. Aus Fehlern lernt man...

    Danke.

    mustino



  • (D)Evil schrieb:

    ...Er macht sehr viel Scheiße in 10 Zeilen-Code ...

    Japp - aber mit string wär das nicht passiert. 😃

    Deswegen wiederhole ich meine Frage:

    Simon2 schrieb:

    mustino schrieb:

    ...

    class ExampleDocument {
    	private:
    		char* path;
    

    Warum nicht string ?

    Das hätte aus

    ExampleDocument::ExampleDocument(string tmp_path, bool newdocument, bool typeInput) {
        this->inputfile="inputFile.dat";
        this->outputfile="outputFile.dat";
        string file;
        string tmp_string;
    
        if(typeInput){
            file = this->inputfile;
        }else{
            file = this->outputfile;   
        }
    
        tmp_string = tmp_path+file;
    
        this->path = const_cast<char*>(tmp_string.c_str());
    
        if(newdocument){
            fstream fs(this->path, ios::out);
            fs.close();   
        }
    }
    

    =>

    ExampleDocument::ExampleDocument(string tmp_path, bool newdocument, bool typeInput) {
        inputfile="inputFile.dat";
        outputfile="outputFile.dat";
    
        string file = path;
        file += typeInput ? outputfile : inputfile; 
        if(newdocument){
            fstream fs(file.c_str(), ios::out);
            fs.close();   
        }
    }
    

    gemacht - was

    Übrigens1: Im Originalcode wird die Membervariable path jedesmal um einen Dateinamen erweitert:
    1. Call -> "\meinDir\irgendwo\inputFile.dat"
    2. Call -> "\meinDir\irgendwo\inputFile.datinputFile.dat"
    3. Call -> "\meinDir\irgendwo\inputFile.datinputFile.datinputFile.dat"
    ...
    ich glaube nicht, dass das gewollt ist (habe das deswegen in meinem Code rausgemacht).

    Übrigens2: Da sich Input- und Outputfile nicht nur im Namen unterscheiden, sondern auch im Zugriff(verschiedene "openmodes", mal read mal write, ....), würde ich nicht versuchen, dieses Aufgaben "zusammenzulegen".

    Ansonsten gäbe es noch einiges zum Design zu sagen, aber das ist noch ein weites Feld, auf dem Du vermutlich erstmal selbst ein wenig Erfahrung sammeln solltest...

    Gruß,

    Simon2.


Anmelden zum Antworten