Entwickler-Ecke
IO, XML und Registry - StreamReader array index out of range nach ca 6,7 Mio Zeilen
elchgesicht - Di 28.09.10 20:04
Titel: StreamReader array index out of range nach ca 6,7 Mio Zeilen
Hallo zusammen,
erst mal als Basisinfo: ich bin neu unterwegs mit c#, programmiere aber seit Jahren in diversen anderen Sprachen. Nun hab ich folgendes Problem: ich muss ein sehr großes Logfile parsen, ca 12 Mio Zeilen.
Nun verwende ich die Klasse StreamReader. Bei kleinen Testdateien läuft alles super. Bei den großen realen Exemplaren ist allerdings nach ca 6,7 Mio Zeilen Schluss.
Fehler: Array Index out of range.
Das Problem ist, es muss ein klasseninterner Index sein, der da voll läuft, da ich selber keinen Index oder ein Array verwende.
Frage: Kennt jemand das Problem?
Frage: Gibt es eine einfache Möglichkeit, eine Datei wirklich Zeilenweise zu lesen, ohne dass ein Puffer (außer einer meiner Wahl) beschrieben wird. ?
Ich bin dankbar für alle Tipps.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| private void readFile() { string line = ""; if ((char)this.stream.Peek()=='T') { this.stream.ReadLine(); }
uint linecounter=0; while((line = this.stream.ReadLine())!=null) { linecounter++;
if (linecounter %100000 == 0) { this.stream.DiscardBufferedData(); Console.WriteLine(linecounter); } if (!(line.StartsWith("\t")) && (Char.IsDigit(line[0]))) {
this.data.numberofcalls++; } } this.stream.Dispose(); this.stream.Close(); } |
Kha - Di 28.09.10 21:30
:welcome: in der EE!
12 Millionen Zeilen :shock: . Ich weiß nicht, warum sich der StreamReader dort verschluckt (kompletter Stack Trace wäre schön :) ), aber bei solchen Datenmengen sollte ReadLine doch sowieso einen derartigen Flaschenhals darstellen, dass eigentlich nur in Frage kommt, den Stream direkt anzusprechen. Oder nicht?
elchgesicht - Di 28.09.10 21:56
Vielen Dank für die Antwort.
In die Richtung habe ich auch schon gedacht, aber leider nichts gefunden was mich weiterbringt. Hättest du vielleicht einen Hinweis nach was oder wo ich suchen könnte für ein Beispiel?
Ich dachte eigentlich, dass ReadLine halt eine Zeile ließt und den Puffer dann bei der nächsten überschreibt. Aber irgendwas scheint intern mitzulaufen, dass es nicht funktioniert.
Kha - Di 28.09.10 22:12
Nunja, einen Buffer in der gewünschten Größe reservieren und Stream.Read aufrufen. Wie es der StreamReader intern auch macht.
Gut, sollte es nicht um ASCII gehen, wird das Deokdieren dann noch einmal spannend ;) .
Yogu - Do 30.09.10 20:17
elchgesicht hat folgendes geschrieben : |
C#-Quelltext 20: 21:
| /* ... */ if (!(line.StartsWith("\t")) && (Char.IsDigit(line[0]))) | |
Bist du dir sicher, dass in jeder Zeile mindestens ein Zeichen steht? Andernfalls würde der Zugriff auf das erste Zeichen eine Exception werfen.
Außerdem denke ich, dass die linke Bedingung sinnlos ist, denn wenn das erste Zeichen eine Ziffer ist, kann es kein Tabulator sein...
elchgesicht - Do 30.09.10 21:06
Diese Zeile war noch Teil der "Lesestudie" und wird definitiv noch geändert. Gestern habe ich mit einem anderen Tool (das neue soll dieses ersetzen, leider) eine Datei parsen müssen mit 21 GB Größe. Da werde ich noch jede Nanosekunde raus holen müssen, sonst dauert das geparse später mal ewig.
Das Ganze wird auch noch eine nette "Performancestudie" für .NET. Mal sehen was raus kommt.
Trotzdem danke für den Hinweis.
Kha - Do 30.09.10 22:53
elchgesicht hat folgendes geschrieben : |
Das Ganze wird auch noch eine nette "Performancestudie" für .NET. Mal sehen was raus kommt. |
Das Einlesen einer Datei sollte ja wohl in allen Sprachen gleich langsam sein ;) . Bei ganz harten Fällen kann das Parsen auch in einen zweiten Thread verlagert werden.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!