Große Dateien mit möglichst kleinem Aufwand lesen?

Sturmkoenig

Grünschnabel
Hallo zusammen,
ich versuche gerade größere Dateien mit möglichst kleinem Speicheraufwand in Arrays einzulesen, nur stoße ich hierbei auf ein Problem:
wenn ich die Zeilen in der 2. Schleife einlesen lasse, kommt nichts Gescheites dabei herraus, d.h. es kommt praktisch gar nichts ins Feld.
Wenn ich es aber in der oberen Schleife rausschreiben lasse, geht es problemlos.

Ich hoffe ich nerve nicht zusehr mit dieser Anfängerfrage... :(

Vllt. könnt ihr mir auch gleich erklären wie man es insgesamt besser machen kann, viel Text sauber in Arrays zu lesen. Danke im Vorraus. :)


Code:
ifstream lesen(datei, ios::in);
	if(lesen.good()) {
		lesen.seekg(0L,ios::beg);

		m_strMultiline += "Caching File...";

		while(!lesen.eof()) {
			num_lines++;
			lesen.getline(zeile_temp, 300);
			//m_strMultiline += zeile_temp;
			laenge_bin=strlen(zeile_temp);
			if(laenge_bin>laengste_zeile) laengste_zeile=laenge_bin;
		}

		char** zeilen = new char*[num_lines];
		for(int i=0; i<num_lines; i++)
			zeilen[i] = new char[laengste_zeile];

		m_strMultiline += "Reading File...";

		lesen.seekg(0L,ios::beg);
		num_lines=0;
		while(!lesen.eof()) {
			lesen.getline(zeilen[num_lines], laengste_zeile);
			m_strMultiline += zeilen[num_lines];
			num_lines++;
		}
	}
 
Eine erprobte Möglichkeit ist folgende:
Code:
    std::vector<char> buffer;      //- einen char-vector als buffer machen
  
    //- Datei in Stringstream lesen
    ifstream is( strProject.c_str() ); //- strProject ist ein std::string mit dem Dateinamen
    if ( !is.good() ) return false;

    //- Größe feststellen
    is.seekg( 0, ios_base::end );         //- aufs Ende setzen
    int size = is.tellg();                //- size enthält jetzt die Anzahl von Bytes in Datei
    if ( size < 1 ) return false;         //- lohnt nicht, abbruch
  
    is.seekg( 0, ios_base::beg );         //- wieder auf Anfang setzen

    buffer.resize( size + 1 );            //- buffergrösse korrigieren
    is.get( &buffer[0], size + 1, '\0' ); //- alles auf einmal in buffer lesen
Danach hast du einen std::vector von chars, der die komplette Datei enthält. Ich habe diese Methode vor zwei Jahren getestet und sie hat unter verschiedenen anderen Varianten die besten Ergebnisse erbracht bei Dateien > 1MB. Es würde mich interessieren, ob es da noch was Fixeres gibt, das mir entgangen ist.

(Dass die Buffergrösse erst nach Konstruktion des Buffers erfolgte, hatte programmtechnische Gründe, auf die ich hier nicht eingehen kann.)
 
Großes Lob für dieses Lösungsweg!
Darauf wäre ich mit meinen Anfängerkenntnissen nie gekommen.
Nur stellt sich für mich nun die Frage, wie ich nun die einzelnen Zeilen in Arrays aufspalten kann, so wie ich das am anfang vorhatte?
 
Der Text befindet sich zu diesem Zeitpunkt ja bereits im Speicher. Du kannst die Zeilen trennen, indem du darin nach '\n' suchst - dem Zeilentrenner. Du könntest auch einen istringstream benutzen (wie mit einem File, aber Eingabe aus string).

Übrigens ist mein Lösungsvorschlag eigentlich nicht so besonders speichereffizient - er ist aber schnell. Das war nämlich der Grund, warum ich optimiert hatte. Ich hatte mich bei deinem Post wohl verlesen, oder vielleicht tue ich es jetzt. ;) Tut mir leid, falls die Lösung zu viel Speicherplatz benötigt, es ist jedenfalls keine schlechte Lösung.
 

Neue Beiträge

Zurück