ofstream



  • Doch, sie wird schon geöffnet, du kannst schon Daten hineinschreiben.
    Wenn du 1000 Dateien benötigt, dann musst du auch 1000 ofstream Objekte erzeugen. Warum sollten sich stream Klassen anders verhalten als andere Klassen?
    Unter Win32 gibt es übrigens eine fiese Stolperfalle, irgendwo ist eine Konstante FILE_MAX (oder so ähnlich) definiert, die festlegt, wieviele Dateien (egal ob fopen/fstream) gleichzeitig geöffnet sein dürfen.



  • Ja, von dieser "Falle" habe ich gehört. Mmhh..ok. Dann werde ich mal weiterrumprobieren und dann höchstwahrscheinlich später weitere Fragen haben 😉

    Vielen Dank schonmal

    lg, freakC++


  • Administrator

    freakC++ schrieb:

    Hier wird eine Datei erstellt, aber noch nicht geöffnet.

    Wie kommst du auf den Unsinn? Das File wird erstellt und geöffnet.

    freakC++ schrieb:

    Angenommen, ich möchte nun 1000 Dateien erstellen, die einfach durchnummeriert sind. Wie stellt man sowas an?

    Auf die ganz billige und langsame Art:

    for(int i = 0; i < 1000; ++i)
    {
      std::istringstream iss;
      iss << "name_" << i;
      std::ofstream out(iss.str().c_str());
    }
    

    freakC++ schrieb:

    ... oder geht das auch irgendwie kürzer, denn die Objekte müsste ich ja auch alle wieder zerstören?

    Man könnte theoretisch den Stream wieder benutzen. Schliesslich gibt es Methoden für open und close . Viel wird es wahrscheinlich nicht bringen, schliesslich muss intern trotzdem immer wieder ein neuer filebuf erstellt und assoziert werden. Und auf dem Filesystem muss ständig ein File geöffnet und wieder geschlossen werden.

    Grüssli



  • Evtl. müsste man einen andere Weg einschlagen: eine leere Datei anlegen und diese tausendmal kopieren. Weil dann wird nichts geöffnet, außer der ersten Datei. Alles andere macht das OS. Natürlich muß man dann die nativen OS-Funktionen oder boost.filesystem dafür benutzen.

    Was schneller und Resourcen-schonender ist, muß man natürlich messen.



  • Dravere schrieb:

    for(int i = 0; i < 1000; ++i)
    {
      std::istringstream iss;
      iss << "name_" << i;
      std::ofstream out(iss.str().c_str());
    }
    

    Was das ein Test? 🤡
    Muß natürlich ein ostringstream oss sein. 😃

    Und wenn man drei Anschläge sparen will, man braucht keinen Namen bei

    //std::ofstream out(oss.str().c_str());
    std::ofstream(oss.str().c_str());
    


  • Hallo,
    ja ich habe da wohl erst was falsch verstanden. Die Datei wird also angelegt und geöffnet. Ich glaube, dass ich einfach damit rumspiele muss, da ich für die ganze Dateiverarbeitung unter C++ noch kein Gefühl habe. Das wird aber schon kommen 😉

    Vielen Dank
    lg, freakC++



  • freakC++ schrieb:

    Hallo,
    ja ich habe da wohl erst was falsch verstanden. Die Datei wird also angelegt und geöffnet. Ich glaube, dass ich einfach damit rumspiele muss, da ich für die ganze Dateiverarbeitung unter C++ noch kein Gefühl habe. Das wird aber schon kommen 😉

    Vielen Dank
    lg, freakC++

    Verzichte generell auf open und close.
    open macht der Konstruktor und close macht der Destruktor.


  • Administrator

    volkard schrieb:

    Was das ein Test? 🤡
    Muß natürlich ein ostringstream oss sein. 😃

    Newbie-Codesicherung :p
    Oder einfach schnelles hingetippsel ohne grosse Kontrolle 😉

    volkard schrieb:

    Verzichte generell auf open und close.
    open macht der Konstruktor und close macht der Destruktor.

    Hier würde noch ein Stichwort sehr gut dazupassen: RAII.

    Grüssli



  • Aus meiner Quelle habe ich aber gelernt, dass close() durchaus benutzt werden sollte, denn

    1.) Es gehen keine Daten verloren, falls das Programm nicht normal beendet wird.

    2.) Die Anzahl der Dateien, die in einem Programm geöffnet sein dürfen, sind begrenzt.

    So argumentiert mein Büchlein 😉

    lg, freakC++



  • freakC++ schrieb:

    Aus meiner Quelle habe ich aber gelernt, dass close() durchaus benutzt werden sollte, denn

    1.) Es gehen keine Daten verloren, falls das Programm nicht normal beendet wird.

    Nutze bitte den Destruktor! Der wird auch bei Exceptions ausgeführt.

    freakC++ schrieb:

    2.) Die Anzahl der Dateien, die in einem Programm geöffnet sein dürfen, sind begrenzt.

    Nutze bitte den Destruktor! Der wird auch bei Exceptions ausgeführt.

    freakC++ schrieb:

    So argumentiert mein Büchlein 😉

    Nutze bitte den Mülleimer! Uns sag den Namen für die Blacklist.



  • DocShoe schrieb:

    Unter Win32 gibt es übrigens eine fiese Stolperfalle, irgendwo ist eine Konstante FILE_MAX (oder so ähnlich) definiert, die festlegt, wieviele Dateien (egal ob fopen/fstream) gleichzeitig geöffnet sein dürfen.

    Ich komme nur bis 508 mit WinXP_32. Und ihr?

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <sstream>
    using namespace std;
    
    int main()
    {
    	for (int i = 0; ; ++i)
    	{
    		std::ostringstream oss;
    		oss << "D:\\tmp\\"<<"name_" << i << ".tmp";
    		std::ofstream* f=new std::ofstream(oss.str().c_str());
    		if (!*f) return 1;
    		cout<<i<<endl;
    	}
    }
    

    edit: Hat sich erledigt. Ist nur eine Beschränkung der Laufzeitumgebung. Das Betriebssystem funktioniert anscheinend.

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <sstream>
    #include <windows.h>
    using namespace std;
    
    int main()
    {
    	for (int i = 0; ; ++i)
    	{
    		std::ostringstream oss;
    		oss << "D:\\tmp\\"<<"name_" << i << ".tmp";
    		HANDLE f=CreateFile(oss.str().c_str(),GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    		if (f==INVALID_HANDLE_VALUE) return 1;
    		cout<<i<<endl;
    	}
    }
    

    Geht bis 120033 bei mir.



  • volkard schrieb:

    Verzichte generell auf open und close.
    open macht der Konstruktor und close macht der Destruktor.

    Warum soll er auf darauf verzichten? Erscheint mir mit open und close übersichtlicher und effizienter. Zwingt zum Nachdenken, wann brauche ich eine Datei und wann nicht mehr.

    Hier der von mir favorisierte Weg:

    #include <fstream.h>
    #include <iostream.h>
    #include <iomanip.h>
    ...
    ofstream test;           // Stream anlegen
    ...
    int     einInt = 10;
    double  einDouble = 10.25;
    ...
    test.open("Test.txt");  // Datei öffnen und einem Stream zuordnen 
    ...
    // Manipulatoren setzen (z.B. für float und double)
    ...
    test.setf(ios::fixed);
    test.setf(ios::floatfield);
    test.setf(ios::showpoint);
    // Einträge in die Datei
    test << "einInt     " << einInt << endl;
    test << "einDouble  " << setprecision(2) << einDouble << endl;
    ...
    ...
    test.close();          // Datei schliessen sobald nicht mehr benötigt
    

    Bei einer Mehrzahl von solchen Dateien muss man das auch mehrfach machen. Die Deklarationen ofstream .... sind wohl zwingend einzeln zu machen. Die open und close können auch über Schleifen mit verschiedenen Stream- und Dateinamen laufen, die man als Char-Strings zusammenbastelt.



  • berniebutt schrieb:

    Hier der von mir favorisierte Weg:

    #include <fstream.h>
    #include <iostream.h>
    #include <iomanip.h>
    ...
    ofstream test;           // Stream anlegen
    ...
    int     einInt = 10;
    double  einDouble = 10.25;
    ...
    test.open("Test.txt");  // Datei öffnen und einem Stream zuordnen 
    ...
    // Manipulatoren setzen (z.B. für float und double)
    ...
    test.setf(ios::fixed);
    test.setf(ios::floatfield);
    test.setf(ios::showpoint);
    // Einträge in die Datei
    test << "einInt     " << einInt << endl;
    test << "einDouble  " << setprecision(2) << einDouble << endl;
    ...
    ...
    test.close();          // Datei schliessen sobald nicht mehr benötigt
    

    Und hier meiner:

    #include <fstream.h>
    #include <iostream.h>
    #include <iomanip.h>
    ...
    int     einInt = 10;
    double  einDouble = 10.25;
    ...
    {//<<-- Guchst Du hier
      ofstream test("Test.txt");  // Stream anlegen und Datei öffnen und einem Stream zuordnen 
      ...
      // Manipulatoren setzen (z.B. für float und double)
      ...
      test.setf(ios::fixed);
      test.setf(ios::floatfield);
      test.setf(ios::showpoint);
      // Einträge in die Datei
      test << "einInt     " << einInt << endl;
      test << "einDouble  " << setprecision(2) << einDouble << endl;
      ...
      ...
      // automatisch Datei schliessen sobald nicht mehr benötigt
    }//<<-- Und hier
    

    berniebutt schrieb:

    Bei einer Mehrzahl von solchen Dateien muss man das auch mehrfach machen. Die Deklarationen ofstream .... sind wohl zwingend einzeln zu machen. Die open und close können auch über Schleifen mit verschiedenen Stream- und Dateinamen laufen, die man als Char-Strings zusammenbastelt.

    Ich sehe keine Mehrzahl von Datei-Objekten. Legst Du die ostreams-Objekte außerhalb der Schleife an brauchst deswegen close? Mach sie doch lokaler.



  • berniebutt schrieb:

    Warum soll er auf darauf verzichten?

    Exceptions.

    Erscheint mir mit open und close übersichtlicher

    Es ist also übersichtlicher, zuerst ein Dummy-Objekt zu erstellen und dann erst die gewünschte Datei zu öffnen?

    und effizienter.

    Es ist also effizienter, zuerst ein Dummy-Objekt zu erstellen und dann erst die gewünschte Datei zu öffnen?

    Zwingt zum Nachdenken, wann brauche ich eine Datei und wann nicht mehr.

    Ich lege genau dann mein fstream-Objekt an, wenn ich die Datei brauche. Also überlege ich wohl mehr, wann ich das Objekt brauche, als du, wenn du es einfach irgendwann mal vorher anlegst.

    Die Deklarationen ofstream .... sind wohl zwingend einzeln zu machen. Die open und close können auch über Schleifen mit verschiedenen Stream- und Dateinamen laufen, die man als Char-Strings zusammenbastelt.

    Versteh ich nicht. Was soll mich daran hindern, ofstream-Objekte in einer Schleife zu erzeugen?



  • @volkard & Michael.E
    Ich sehe da keinen oder wenig Widerspruch in unseren Aussagen. Objekte legt man an wenn man sie braucht und gibt sie frei wenn man sie nicht mehr braucht. Dies bei einer Vielzahl der Stream-Objekte als Code-Beispiel zu zeigen ist nicht möglich oder verwirrt den Fragesteller. Wir wollen doch uns nicht gegenseitig überzeugen, sondern dem Fragesteller eine Hilfe geben. Nachdenken und machen soll er selbst! 🙂



  • berniebutt schrieb:

    @volkard & Michael.E
    Ich sehe da keinen oder wenig Widerspruch in unseren Aussagen. Objekte legt man an wenn man sie braucht und gibt sie frei wenn man sie nicht mehr braucht. Dies bei einer Vielzahl der Stream-Objekte als Code-Beispiel zu zeigen ist nicht möglich oder verwirrt den Fragesteller. Wir wollen doch uns nicht gegenseitig überzeugen, sondern dem Fragesteller eine Hilfe geben. Nachdenken und machen soll er selbst! 🙂

    An open und close erkennt man schlechten Code und schlechte Bücher.
    Fertig.



  • volkard schrieb:

    An open und close erkennt man schlechten Code und schlechte Bücher. Fertig.

    Ein schlechter Code ist nur jener, der ein Programm zum Absturz bringt, instabil macht, oder unnötig Ressourcen (Laufzeit, Speicher) beansprucht.
    daddeldu - ich habe fertig! :p



  • berniebutt schrieb:

    Ich sehe da keinen oder wenig Widerspruch in unseren Aussagen.

    Ähh, doch. Du willst open und close benutzen und volkard und ich wollen das nicht. Reicht das nicht?

    Objekte legt man an wenn man sie braucht und gibt sie frei wenn man sie nicht mehr braucht.

    Machst du anscheinend nicht.

    Wir wollen doch uns nicht gegenseitig überzeugen,

    Doch.

    sondern dem Fragesteller eine Hilfe geben.

    Das geschieht dann automatisch.



  • Hallo zusammen,
    nachdem eigentlich alles erfolgreich funktioniert hat, stehe ich nun vor einem Problem. Ich möchte, dass der Benutzer einen Dateipfad mit dem Dateinamen und der Endung eingibt und daraufhin die entsprechende Datei erstellt wird.

    Wenn ich im Quelltext den ganzen Pfad eingebe, dann funktioniert es, doch sobald der Benutzer über die Konsole den Pfad eingibt, funktioniert nichts mehr. Könnt ihr mir sagen warum?

    Hier ist der Quelltext:

    #include <iostream> 
    #include <string>
    #include <fstream>
    using namespace std; 
    
    void getDir(string& fl1, string& fl2, string& of1) //Liest Dateipfade aus
    {
    	string dirf1, dirf2, diro1;
    	cout << "Bitte geben Sie den Pfad der ersten Datei an!\n"
    		 << endl;
    	getline(cin, dirf1);
    
    	cout << "Bitte geben Sie den Pfad der zweiten Datei an!\n" 
             << endl;
    	getline(cin, dirf2);
    
    	cout << "Bitte geben Sie das Zielverzeichnis mit Dateinamen an!\n" 
             << endl;
    	getline(cin, of1);
    	if(dirf1 == dirf2)
    		cout << "Sie muessen zwei verschiedenen Dateien angeben!" << endl;
    	else
    	{
    		fl1 = dirf1;
    		fl2 = dirf2;
    	}
    
    }
    
    int main()
    {
    	string inFile1, inFile2, outFile;
    	getDir(inFile1, inFile2, outFile);
    	//ifstream inf1(inFile1.c_str()),
    	//		 inf2(inFile2.c_str());
    
    	ofstream outf(outFile.c_str()); //Datei wird nicht angelegt. Die untere if - Bedingung ist true
    
    	cout << outFile << endl; //Der Pfad stimt. Wenn ich ihn direkt in den Konstruktor von outf eingebe, dann funktioniert alles
    	if(/*!inf1|| !inf2 ||*/ !outf)
    	{
    		cout << "Fehler beim Oeffnen/Schreiben der Dateien" << endl;
    		return 0;
    	}
    
    	return 0;
    }
    

    Wisst ihr, wo der Fehler lieg?

    Vielen Dank
    lg, freakC++



  • Der Pfad stimmt nicht. 😉


Anmelden zum Antworten