(Für mich) seltsames Verhalten



  • Ich möchte mehrere Dateien einlesen, und diese dann zusammengepackt in einer Datei wieder speichern. Damit die Schnelligekit nicht so sehr an der Festplatte leidet, habe ich mir gedacht erst eine Datei in einem Container zwischenzuspeichern und den dann mit einem Mal zu schreiben.
    Hier ist der Code:

    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <vector>
    
    using namespace std;
    
    void processFile(string const& filename_in, string const& filename_out) {
    	cout << filename_in;
    	ifstream fs(filename_in);
    	vector<string> container;
    	char buffer[1024];
    	try {
    		while (fs.getline(buffer,1024))	
    			container.push_back(buffer);
    	} catch(...) {
    		cout << "Buffer Overflow\nNächste Datei wird eingelesen" << endl;
    	}
    	fs.close();
    	ofstream os(filename_out, ios::app);
    	for (unsigned int i = 0; i < container.size(); ++i) {
    		os.write(container[i].c_str(), container[i].size());
    	}
    	os.close();
    }
    
    int _tmain(int argc, _TCHAR* argv[]) {
    	for (int i = 1; i <= 38; ++i) {
    		stringstream ss;
    		ss << i << ".txt" << endl;
    		processFile(ss.str(), "words.txt");
    	}
    	cout << "Fertig" << endl;
    	cin.get();
    	return 0;
    }
    

    Wenn die Dateien unter 100 MB groß sind, funktioniert auch alles. Nur wenn sie größer als 100 kb sind, alloziiert mein Programm wie ein verrückter Speicher, bis Windows nichts mehr hergibt und abstürzt. Anstatt vector habe ich auch mal deque ausprobiert, das hat es aber auch nicht getan.
    Weiß da jemand weiter?



  • Denksportler schrieb:

    Damit die Schnelligekit nicht so sehr an der Festplatte leidet, habe ich mir gedacht erst eine Datei in einem Container zwischenzuspeichern und den dann mit einem Mal zu schreiben.

    Vergiss es. Dein geliebtes Windows (bzw. die C++-Library) macht dies intern, schreibt in einen Buffer und wenn der genügend voll ist, schreibt es diesen auf die Festplatte.
    Die Performanz wird ganz sicher nicht an dem leiden, merklich besser wie es so ist, kann es gar nicht werden.



  • Ich habs so jetzt mal abgeändert:

    #include "stdafx.h"
    
    using namespace std;
    
    void processFile(string const& filename_in, string const& filename_out) {
    	cout << filename_in << endl;
    	ifstream fs(filename_in);
    	if (!fs) {
    		cout << "Konnte " << filename_in << " nicht \x94 \bffnen!" << endl;
    		return;
    	}
    	ofstream os(filename_out, ios::app);
    	char buffer[1024];
    	while (fs.getline(buffer,1024))	{
    		os << buffer << endl;
    		memset(buffer,0,sizeof(buffer));
    	}
    	fs.close();
    	os.close();
    }
    
    int _tmain(int argc, _TCHAR* argv[]) {
    	for (int i = 1; i <= 38; ++i) {
    		stringstream ss;
    		ss << i << ".txt";
    		processFile(ss.str(), "words.txt");
    	}
    	cout << "Fertig" << endl;
    	cin.get();
    	return 0;
    }
    

    Nur dauert es da 10 Minuten um 200 MB zu kopieren. Das ist etwas sehr langsam. Gibt es da irgendwelche Tricks, um das zu Beschleunigen?



  • Ich habs jetzt nicht getestet und ich kenne mich nicht aus, wie NTFS das intern macht (unter ext3 geht das sicher schneller), aber out zu öffnen dürfte etwas bringen:

    using namespace std;
    
    void processFile(string const& filename_in, ofstream& out) {
    	cout << filename_in << endl;
    	ifstream fs(filename_in);
    	if (!fs) {
    		cout << "Konnte " << filename_in << " nicht \x94 \bffnen!" << endl;
    		return;
    	}
    	os << fs.rdbuf();
    	// fs.close(); braucht es nicht
    }
    
    int _tmain(int argc, _TCHAR* argv[]) {
    	ofstream os("words.txt", ios::app);
    	for (int i = 1; i <= 38; ++i) {
    		stringstream ss; ss << i << ".txt";
    		processFile(ss.str(), out);
    	}
    	os.close();
    	cout << "Fertig" << endl;
    	cin.get();
    	return 0;
    }
    


  • Das werde ich mal ausprobieren.
    Aber nicht für jede Linie zu flushen hat auch schon einen erheblichen Geschwindigkeitsschub gegeben.

    void processFile(string const& filename_in, string const& filename_out) {
    	cout << filename_in << endl;
    	ifstream fs(filename_in);
    	if (!fs) {
    		cout << "Konnte " << filename_in << " nicht \x94 \bffnen!" << endl;
    		return;
    	}
    	ofstream os(filename_out, ios::app);
    	char buffer[1024];
    	while (fs.getline(buffer,1024))	{
    		os << buffer << "\n";
    		memset(buffer,0,sizeof(buffer));
    	}
    	os.flush();
    	fs.close();
    	os.close();
    }
    
    int _tmain(int argc, _TCHAR* argv[]) {
    	for (int i = 1; i <= 38; ++i) {
    		stringstream ss;
    		ss << i << ".txt";
    		processFile(ss.str(), "words.txt");
    	}
    	cout << "Fertig" << endl;
    	cin.get();
    	return 0;
    }
    

Anmelden zum Antworten