| 

.NET C# Java Javascript Exception

4
Hallo,

trotz umfangreicher Suche im Web konnte ich keine Antwort für mein Problem finden. Ich möchte eine Datei (Text) mit C# schrittweise einlesen, die größer als 40 GB ist. Gedacht hatte ich mir das so:

Es wird irgendeine Art Stream soweit mit dem Inhalt der Datei gefüllt, bis dieser voll ist. Dann erfolgt eine Bearbeitung. Die Endposition wird dann als Startposition für den wiederholten Stream-Aufruf gesetzt. Der Vorgang wiederholt sich solange, bis die gesamte Datei abgearbeitet ist. Bisher fand ich keinen Stream-Konstruktor, mit dem das möglich wäre.

Gibt es eine Art Stream, der das zulässt, oder eine mir noch nicht bekannte Möglichkeit, mit der das so oder ähnlich möglich ist?

Vielen Dank schon jetzt für eventuelle Antworten!
14.03.2011
Bastler 61 3
8 Antworten
2
Hi,

in welcher Art wird der Inhalt weiterverarbeitet?
Muss der gesamte Dateiinhalt eingelesen werden?

Kannst Du die Dateiverarbeitung auf kleinere Teile splitten, diese weiter verarbeiten
und dann die nächsten Teile einlesen?

Welche Frameworkversion verwendest Du?
Bei .NET 4.0 gibt es afaik für solche Szenarien die Memory mapped file.

Edit:
So könntest Du bspw zeichenweise aus der Datei lesen
// chunksize ist die Zeichenanzahl
using (StreamReader stream = new StreamReader(File.OpenRead(@"C:\BigFile.dat"))
{
char[] buffer = new char[chunksize];
while (stream.Peek() >= 0)
{
int readCount = stream.Read(buffer, 0, chunksize);
string result = new string(buffer, 0, readCount);
}
}


Mit einer kleinen Anpassung auch auf IEnumerable Rückgabe umbaubar.
14.03.2011
KHoffmann 939 6
Bei 40GB funktioniert das aber leider nicht - oder irre ich mich?
Bastler 14.03.2011
Mit 4.5GB keine Probleme. Es wird eine Datei geöffnet, der StreamReader läuft rüber, es werden immer nur die Anzahl Zeichen in result geschrieben, die über "chunksize" angegeben wurden.
KHoffmann 14.03.2011
Sehr bedanken möchte ich mich schon jetzt für alle Bemühungen in meiner Sache! Morgen werde ich mich erst mal in "MemoryMappedFile-Klasse" einarbeiten, die mir unbekannt war. Anschließend werde ich mich wohl mal genauer mit StreamReader auseinandersetzen. Aus irgendeinem Grund hatte das "Ding" bei mir bisher versagt. Morgen, ab 20 Uhr, werde ich mich hoffentlich sehr bedanken, oder eine erweiterte Frage stellen.
Bastler 14.03.2011
0
Nach nochmaligem, genauen Lesen deiner Frage habe ich den subtilen Hinweis verstanden, dass du dies abends in deiner Freizeit "bastler"st und offensichtlich noch am Anfang stehst.

Daher ein Lösungsvorschlag (FÜR TEXTDATEIEN MIT ZEILENSCHALTUNG)

StreamReader sr = new StreamReader(File.OpenRead(@"c:\bigfile.dat"));
string actualLine = "";
while (!sr.EndOfStream)
{
actualLine = sr.ReadLine();
Console.WriteLine(actualLine);
}


Statt der Ausgabe in das Ausgabefenster (das dauert bei 40 GB etwas ...) sollte dann deine Verarbeitung kommen.
15.03.2011
nabuchodonossor 1,2k 4
0
Hi,

vielen Dank für alle Kommentare. Vielleicht ist meine Frage nicht verständlich genug formuliert worden, deshalb hier mal der Code (als Fragment), den ich bisher nutze. Ich möchte auf keinen Fall 40 GB auf einen Schlag einlesen! Ich wollte diese schon in kleinen "Häppchen" bearbeiten.

Stream inRead = File.OpenRead(s1);
Stream kRead = File.OpenRead(s2);
Stream outWrite = File.Create(s3);

BufferedStream inStream = new BufferedStream(inRead);
BufferedStream kStream = new BufferedStream(kRead);
BufferedStream outStream = new BufferedStream(outWrite);

try
{
inStream.Position = kStream.Position = outWrite.Position = 0;
while(inStream.Position < inStream.Length )
// Verarbeitung
}
...

Über Verbesserungen würde ich mich sehr freuen. Um eine byte für byte-Bearbeitungen komme ich leider nicht herum. Mit sehr großen Dateien hatte ich Schwirigkeiten.

Vielen Dank schon jetzt.
15.03.2011
Bastler 61 3
Floyd 11,0k 3 9
1
Edit: Code-Formatierung hinzugefügt
Floyd 15.03.2011
Also der Code macht für mich grade gar keinen Sinn.
Müsste die Bedingung im while nicht immer true sein, da im Endeffekt eine 0 gesetzt wird?
Hinzu kommt zumindest für mich, dass ich mit dem Miniteil nicht wirklich erkennen kann, was Du damit bewirken willst.
KHoffmann 15.03.2011
Der Code läuft - er ist getestet. Die Schleife bricht korrekt ab. Arrays werden nicht benötigt. In d. Schleife läuft eine Berechnung ab, anschießend wird der Ergebniswert, der keine Übergröße erreichen kann, an der Position in den outStream geschrieben.
Bastler 15.03.2011
Was heißt "hatte ich Schwierigkeiten"? Kam eine Exception oder ein nicht erwartetes Verhalten?
Und bitte editiere Deine Beiträge und mach nicht immer antworten, hier ist ja reines Chaos.
KHoffmann 15.03.2011
Ohne Fehlermeldung wurde das Programm kompiliert. Kleine Dateien, ca. 30MB, laufen zwar zeitaufwendig, aber fehlerfrei durch. Die genaue Grenze habe ich noch nicht ermitteln können, das Programm verhakt sich und arbeitet einfach nicht mehr.
Bastler 15.03.2011
D.h. du weißt nicht, ob bspw. Arbeitsspeicher knapp ist? Ich habe so einen Fall noch nicht gehabt und ohne eine genaue Fehlerbeschreibung ist eine Hilfe relativ schwer. Mit dem von mir geposteten Code konnte ich problemlos Dateien bis zu 20GB verarbeiten.
Der Fehler liegt denk ich an Deinem Code.
KHoffmann 15.03.2011
Soeben hatte ich deinen Code bei mir getestet. Ich erhielt das selbe Ergebnis wie zuvor. Daraufhin habe ich mal meine Firewall ausgeschaltet und - ich glaube es nicht - beide Codes laufen auf einmal richtig!!! Eine Erklärung fällt mir dazu irgendwie nicht wirklich ein. Sehr dankbar bin ich allen, die mir geschrieben haben. Besonders erfreut war ich über den Link-Hinweis zu MemoryMappedFile!!! Ich werde jetzt keine Hilfe mehr benötigen und bedanke mich bei euch allen.

Mit herzlichen Grüßen

Bastler
Bastler 15.03.2011
Hi Bastle,

von solchen Codes würde ich mir mehr wünschen. Ein Stream, der sich selbst hochzählt, ist selten anzutreffen.Die "Fake-Limitierung" in der while ist unschwer zu erkennen. Bitte schreib mehr Code. Solltest du woanders publizieren, gib einen Hinweis.
Bruno 16.03.2011
0
Vielleicht hilft Dir ja die Antwort zu dieser Frage weiter.
15.03.2011
Joachim 2,8k 3 9
-1
Der Inhalt wird direkt im Stream, byte für byte bearbeitet. Eine Splittung auf kleine Teile ist möglich. NET 4.0 wird verwendet. Zudem kommt es auf keinerlei Zeitkosten an. Nur die Qualität muß stimmen.
14.03.2011
Bastler 61 3
-1
Besser gesagt, 4 byte-Werte werden zu einem int-Wert "zusammengeschoben", dann abgearbeitet. Der Stream könnte dann durch flush freigegeben werden und neu bestückt werden.
14.03.2011
Bastler 61 3
-1
Die Lösung mit:

StreamReader stream = new StreamReader(File.OpenRead(@"C:\BigFile.dat")

wird bei 40GB nicht funktionieren - oder irre ich mich?
14.03.2011
Bastler 61 3
2
die frage legt nahe, dass du es noch nicht ausprobiert hast. hast du?
nabuchodonossor 15.03.2011
Ich denke eher nicht, dass es schon ausprobiert wurde.
KHoffmann 15.03.2011
-3
Naja ich würde mal sagen du bräuchstest min. 40 GB Arbeitsspeicher ... ansonsten hat er das Problem die Datei zwischenzuspeichern...
15.03.2011
1
Wenn er die komplette Datei einlesen will hast Du recht.
Wenn ich aber nur die Datei öffne und mich in bestimmten Schritten im Dateistrom bewege, gibt es keinerlei Probleme.
KHoffmann 15.03.2011

Stelle deine Datei-Frage jetzt!