2009-08-10 25 views
2

Ich habe eine große Textdatei mit mehr als 200.000 Zeilen, und ich muss nur ein paar Zeilen lesen. Zum Beispiel: Zeile 10.000 bis 20.000.So lesen Sie Teildaten aus einer großen Textdatei in C++

Wichtig: Ich möchte nicht die vollständige Datei öffnen und durchsuchen, um diese Zeilen wegen Leistungsproblemen zu extrahieren.

Ist das möglich?

+0

Ich habe es in Fortran gesehen, wir mussten eine Datei von einem Datenzähler (2 Millionen Zeilen) lesen. Also ich bin zuversichtlich, dass es machbar ist – dassouki

Antwort

1

Sie müssen die Datei durchsuchen, um die Zeilenumbrüche zu zählen, es sei denn, Sie wissen, dass alle Zeilen die gleiche Länge haben (in diesem Fall könnten Sie die Zeile "offset = Zeilennummer * line_size_in_bytes" suchen, wobei Zeilennummer von null und Zeile_size_in_bytes zählt) alle Zeichen in der Zeile).

Wenn die Zeilen variable/unbekannte Länge haben, dann können Sie beim ersten Durchlesen des Anfangsoffsets jeder Zeile den Anfang der Zeile indexieren, damit nachfolgende Lesevorgänge den Anfang einer bestimmten Zeile suchen können.

6

Wenn die Zeilen eine feste Länge haben, ist es möglich, nach einer bestimmten Byte-Position zu suchen und nur die gewünschten Zeilen zu laden. Wenn Zeilen eine variable Länge haben, können Sie die gesuchten Zeilen nur finden, indem Sie die Datei analysieren und die Anzahl der Zeilenendezeichen zählen. Wenn sich die Datei selten ändert, können Sie möglicherweise eine ausreichende Leistung erzielen, indem Sie diese Analyse einmal durchführen und dann einen Index der Bytepositionen jeder Zeile beibehalten, um zukünftige Zugriffe zu beschleunigen (vielleicht diesen Index auf Festplatte schreiben, damit er nicht benötigt wird) erfolgt jedes Mal, wenn Ihr Programm ausgeführt wird).

+1

Vorbehalt: Einige Dateiformate enthalten einen Index Ohr den Anfang oder manchmal gegen Ende. Dann lesen Sie den Index und berechnen daraus die Startposition der benötigten Daten. Ja, das ist einfacher und häufiger in Binärformaten, aber ich habe es in einem Textformat gesehen. – dmckee

+0

+1 für die Antwort @dmckee: Ein Index am Anfang scheint kein echtes Problem? Am Ende können Sie wahrscheinlich bis zum Ende suchen und Sie kennen wahrscheinlich die Indexgröße, also scheint es kein großes Problem zu sein? – neuro

+0

@neuro: Das letzte Element eines Indexes am Ende muss ein Offset fester Größe für den Anfang des Indexes sein. Sie suchen bis zum Ende, sichern um einen bekannten Betrag, lesen den Index-Offset, gehen zum Index und fahren von dort fort. Offensichtlich, oder? :) – dmckee

0

Wenn diese Zeilen alle die gleiche Länge haben, können Sie einen Offset für eine bestimmte Zeile berechnen und nur diese Bytes lesen.

Wenn die Zeilen unterschiedliche Länge haben, müssen Sie wirklich die gesamte Datei lesen, um zu zählen, wie viele Zeilen es gibt. Zeilenendezeichen sind nur beliebige Bytes in der Datei.

0

Wenn die Zeile feste Länge haben, berechnen Sie nur den Offset, kein Problem.

Wenn dies nicht der Fall ist (d. H. Eine reguläre CSV-Datei), müssen Sie die Datei durchgehen, um entweder einen Index zu erstellen oder nur die benötigten Zeilen zu lesen. Um das Lesen der Datei ein wenig schneller zu machen, wäre es eine gute Idee, Speicherabbilddateien zu verwenden (siehe die Implementierung, die Teil der Boost-Iostreams ist: http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html).

0

Wie andere angemerkt haben, wenn Sie nicht die Linien der festen Breite haben, ist es unmöglich, ohne den Index zu bauen. Wenn Sie jedoch das Format der Datei kontrollieren, können Sie beim Suchen der Startlinie eine ~ 0 (Protokoll (Größe)) anstelle von 0 (Größe) Leistung erhalten, wenn Sie es schaffen, die Nummer der Zeile selbst zu speichern jede Zeile, dh den Inhalt der Datei in etwa so aussehen haben:

1: val1, val2, val3 
2: val4 
3: val5, val6 
4: val7, val8, val9, val10 

mit diesem Format der Datei, können Sie schnell die benötigte Zeile für binäre Suche finden: fahren Sie in die Mitte der Datei mit der Suche nach. Lesen Sie bis zum nächsten Zeilenumbruch. Lesen Sie dann die Zeile und parsen Sie die Nummer. Wenn die Anzahl größer als das Ziel ist, müssen Sie den Algorithmus in der ersten Hälfte der Datei wiederholen, wenn er kleiner als die Zielzeilennummer ist, dann müssen Sie ihn in der zweiten Hälfte der Datei wiederholen.

Sie müssen auf die Eckfälle achten (zB: Ihr "Anfang" des Bereichs und "Ende" des Bereichs sind auf der gleichen Linie, etc.), aber für mich funktionierte dieser Ansatz ausgezeichnet die Vergangenheit für die Analyse der Logdateien, die das Datum darin hatten (und ich musste die Linien finden, die zwischen den bestimmten Zeitstempeln sind).

Natürlich schlägt dies noch nicht die Leistung des explizit gebauten Index oder der Datensätze fester Größe.

Verwandte Themen