OutOfMemoryException, wenn ich Lesen 500MB FileStream
Ich bin mit Filestream zum Lesen einer großen Datei (> 500 MB) und ich bekomme die OutOfMemoryException.
Lösungen, die über es.
Mein Code ist:
using (var fs3 = new FileStream(filePath2, FileMode.Open, FileAccess.Read))
{
byte[] b2 = ReadFully(fs3, 1024);
}
public static byte[] ReadFully(Stream stream, int initialLength)
{
//If we've been passed an unhelpful initial length, just
//use 32K.
if (initialLength < 1)
{
initialLength = 32768;
}
byte[] buffer = new byte[initialLength];
int read = 0;
int chunk;
while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
{
read += chunk;
//If we've reached the end of our buffer, check to see if there's
//any more information
if (read == buffer.Length)
{
int nextByte = stream.ReadByte();
//End of stream? If so, we're done
if (nextByte == -1)
{
return buffer;
}
//Nope. Resize the buffer, put in the byte we've just
//read, and continue
byte[] newBuffer = new byte[buffer.Length * 2];
Array.Copy(buffer, newBuffer, buffer.Length);
newBuffer[read] = (byte)nextByte;
buffer = newBuffer;
read++;
}
}
//Buffer is now too big. Shrink it.
byte[] ret = new byte[read];
Array.Copy(buffer, ret, read);
return ret;
}
InformationsquelleAutor Alhambra Eidos | 2010-05-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den code, den Sie zeigen, liest alle Inhalte der 500mb Datei in einen zusammenhängenden Bereich im Speicher.
Es ist nicht verwunderlich, dass Sie ein " out-of-memory-Bedingung.
Die Lösung ist, "Tu das nicht."
Was sind Sie wirklich versucht, zu tun?
Wenn Sie möchten, Lesen Sie eine Datei vollständig, es ist viel einfacher als die ReadFully Methode, die Sie verwenden. Versuchen Sie dies:
Aber... mit diesem code wird nicht Ihr problem lösen. Es könnte funktionieren, für eine 500 MB-Datei. Es wird nicht funktionieren, für eine 750 MB Datei oder eine 1 GB-Datei. Irgendwann erreichen Sie die Grenze von Speicher auf Ihrem system und Sie haben die gleiche out-of-memory-Fehler, den Sie begonnen haben.
Das problem ist, dass Sie versuchen, halten Sie den gesamten Inhalt der Datei im Speicher auf einmal. Dies ist in der Regel unnötig und zum scheitern verurteilt ist, da die Dateien in der Größe wachsen. Es ist kein problem, wenn die Dateigröße ist 16k. Auf 500 MB, es ist der falsche Ansatz.
Diesem Grund habe ich mich mehrmals gefragt, was sind Sie wirklich versuchen, zu tun ?
Klingt wie Sie wollen, senden Sie den Inhalt einer Datei aus, um eine ASPNET-Antwort-stream. Das ist die Frage. Nicht "wie zu Lesen, eine 500mb Datei in den Speicher?" Aber "gewusst wie: senden einer großen Datei, um den ASPNET-Response-stream???"
Für dieses, wieder einmal, es ist ziemlich einfach.
Was es tut, ist iterativ, Lesen Sie ein Stück von der Datei, und schreiben Sie das Stück an das Response-stream, bis es nichts mehr zu Lesen in der Datei. Dies ist, was gemeint ist mit "streaming-IO". Die Daten übergibt, durch Ihre Logik, aber nie alle an einem Ort, der nur als ein Strom von Wasser fließt durch die Schleuse. In diesem Beispiel, es gibt nie mehr als 1k Daten im Speicher zu einer Zeit (gut, nicht von den Ihre Anwendung code, sowieso. Es gibt auch andere IO-Puffer tiefer im stack.)
Dies ist ein gemeinsames Muster in IO gestreamt. Lernen Sie es, verwenden Sie es.
Den einen trick beim Pumpen Daten aus ASPNET-Antwort.Ausgabestrom zu setzen, ist
BufferOutput = false
. Standardmäßig ASPNET versucht, Puffer, dessen Ausgang. In diesem Fall (500mb Datei), die Pufferung ist eine schlechte Idee. Einstellung derBufferOutput
- Eigenschaft auf false wird verhindert, ASPNET aus dem Versuch, alle Puffer die Daten der Datei vor dem senden des ersten byte. Verwenden Sie, wenn Sie wissen, dass die Datei, die Sie senden, ist sehr groß. Die Daten werden noch zugestellt bekommen, der browser richtig.- Und auch dies nicht die vollständige Lösung. Sie müssen die Antwort-Header und so weiter. Ich denke, Sie sind sich bewusst, dass, obwohl.
warum willst du die gesamten Inhalte dieser große Datei im Speicher auf einmal? Was sind Sie wirklich versucht, zu tun?
Ich will nur Lesen, eine große Datei in byte [], um es zu senden asp.net Seite wie Antwort. ReadFully Funktion ist der code yoda.arachsys.com. danke !!! yoda.arachsys.com/csharp/readbinary.html
Sie möchten readd 500 MB in den Speicher, und es ist zu scheitern. Das bedeutet, dass Sie nicht genug Speicher haben. Auch die FileStream unterstützt eine Length-Eigenschaft. Sie brauchen nicht zu gehen durch alle Liegestütze der ReadFully() zum Lesen einer ganzen Datei. Nur reservieren eines Puffers der Größe der Länge und einmal gelesen. Ein Ansatz, wie übernommen in ReadFully() ist nur notwendig, wenn Sie nicht wissen, die Länge des Baches vor, es zu Lesen.
Sie wirklich NICHT wollen, zu tun. Sie brauchen nicht zu "error out" auf einer 500mb Datei. Nur Strom ist es, wie ich schon sagte. Die Lösung, die Sie suchen, ist hier genau richtig. Sie scheinen nicht, WIE die Lösung für einige Grund, aber es ist die Lösung, das versichere ich Ihnen.
InformationsquelleAutor Cheeso
Sie verdoppeln Ihre Puffer-Größe bei jeder Umverteilung, was bedeutet, dass die zuvor zugewiesenen Blöcke können nie verwendet werden (Sie effektiv Leck). Mit der Zeit bekommen Sie 500 MB, Sie haben gekaut, bis 1 GB, plus Overhead. In der Tat, könnte es sein, 2 GB, da, wenn du die 512 MB, Ihre nächste Zuteilung von 1 GB. Auf einem 32-bit-system ist, diese Bankrotteure Ihren Prozess.
Da, es ist eine normale Datei, die Sie Lesen, nur mit Abfrage das Dateisystem für seine Größe und preallocate den Puffer in einem Rutsch.
+1: ja, die Zuweisung der Puffer-Größe, die Sie brauchen, ist eine gute Idee... tatsächlich, ich bin überrascht, dass .NET nicht über eine Methode zum Lesen einer ganzen Datei in ein byte-array oder eine andere ähnliche Struktur.
Es funktioniert. Datei.ReadAllBytes msdn.microsoft.com/en-us/library/..., Aber das ist nicht das, was dieses Plakat zu tun. Lesen der bytes, die von einer 500mb Datei in den Speicher, ist in der Regel eine schlechte Idee, und in diesem Fall, ... es ist eine sehr schlechte Idee. Der poster hat ganz klar im Sinn einer primären, noch nicht ausgesprochene Ziel, dass nicht "alle Lesen die bytes einer Datei in den Speicher." Er denkt, die er braucht, zu Lesen, alle bytes, aber es ist nicht wahr.
Nur, um hinzuzufügen, ich habe das gleiche Problem mit meinem Excel-Add-in VSTO. Mein C# - code versucht zu ReadAllBytes zum laden in den raw-Daten in ein 60Mb Excel-Datei, und auch das auslösen einer OutOfMemory-exception.
Sie sollten generell keine Probleme haben, Lesen 60 MB in den Speicher. Sind Sie auf einer memory-constrained system mit virtuellen Speicher deaktiviert?
InformationsquelleAutor Marcelo Cantos
Asp.Net Core Middleware
InformationsquelleAutor Sunil Dhappadhule