2016-04-22 16 views
1

ich in einer Datei lesen bin zu wollen, die in diesem Fall ist 3mb tun dies ca. 50-60 Sekunden dauert, die sehr langsam erscheint. Kann jemand das schneller machen?Stream sehr langsam für große Dateien

string text = null; 
using (StreamReader sr = new StreamReader(file, Encoding.Default)) 
{ 
    string line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     text += (line); 
     backgroundWorker1.ReportProgress(text.Length); 
    } 
} 

Ich brauche auch einen Hintergrund Arbeiter zu verwenden, so dass ich den Prozentsatz berichten kann, die (für Dateien um 500mb bis 1gb)

+2

Haben Sie Ihren Test versucht, ohne mit einem 'System.String' zu verketten, d. H. Die Zeile' text + = (line); –

+0

Vielleicht möchten Sie es nicht pro Zeile lesen, sondern mit einer festen Pufferlänge. – rinukkusu

+0

@ Christian.K Ich tat das und es war sofort. Wie würde ich nun den Text bekommen? – jLynx

Antwort

5

Verwenden Sie einen Stringbuilder geladen sind Ihre Linie zu schaffen - es ist viel leistungsfähiger als String-Verkettung.

using System.Text; 

//... 

StringBuilder text = new StringBuilder(); 
using (StreamReader sr = new StreamReader(file, Encoding.Default)) 
{ 
    string line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     text.Append(line); 
     backgroundWorker1.ReportProgress(text.Length); 
    } 
} 

// ... 
// Do something with the file you have read in. 
Console.WriteLine(text.ToString()); 
+0

Das wird eine NullReferenceException verursachen; sieht so aus als würde 'text' nie initialisiert? –

+0

Aber 'text' _is_ initialisiert ... auf' null' (dritte nichtleere Zeile des Snippets). – Nuffin

+0

Entschuldigung - Fehler beim Kopieren und Einfügen. Jetzt behoben. –

0

Sie diese Zeile verwenden:

string text = System.IO.File.ReadAllText(file); 
+0

Ja, aber dann gibt es keine Möglichkeit, den Fortschritt zu melden (sieht so aus, als ob das für das OP wichtig ist - dann vielleicht nicht). –

+1

Auch wenn er mit großen Dateien zu tun hat, möchte er sie vielleicht nicht alle gleichzeitig im Speicher ablegen (er erwähnt 1GB Dateien in seiner Frage). –

4

Stream sehr langsam für große Dateien C#

nein, ist es nicht. Wenn Sie Ihre grundlegenden Hausaufgaben laufen einen Profiler getan hätte, würden Sie sehen, dass die Zeit verbringen Sie ist NICHT im Stromleser ausgegeben.

text + = (Linie);

Diese Zeile erstellt eine neue Zeichenfolge. Dafür muss neuer Speicher zugewiesen werden. Für eine große Datei ist dies eine erhebliche Menge an Müll erstellt. Und je länger es dauert, desto mehr Kopiervorgänge machen Sie.

Wenn das ist, was Sie verwenden es für

backgroundWorker1.ReportProgress (text.length);

ist es auch nutzlos. Sie können auch eine

int textLength = 0

haben, die Sie dann

gesetzt

textLength + = line.Length

ohne den ganzen Text Manipulation.

Sie haben sollten, dass bekannt. Leistungsproblem? NIEMALS annehmen, IMMER uns ein Profiler - was sehr schnell das Problem gezeigt hätte. Dies ist ein grundlegendes Debugging.

Einige Hintergrund Mathe, btw:

(für Dateien um 500mb zu 1 GB)

Das bedeutet, dass einmal laden Sie 500mb Daten Ihr Code eine 500mb machen (wenn die Datei war Unicode) zu 1GB (String doppelt so groß wie eine ASCII-Datei) Kopiervorgang PER LINE.

Sie können die Speichergeschwindigkeit Ihres Computers nachschlagen. Abhängig vom Server usw.Sie können auf 50 GB pro Sekunde beschränkt sein (High End X99 - die neueren DDR 4 Speicher sind schneller, aber Workstations haben im Allgemeinen viel weniger Kanäle, sind also wieder langsamer) und eine Kopie zählt doppelt (Lesen und Schreiben). Was bedeutet, dass Sie wirklich anfangen in "Szenarien" zu kopieren, die den String überladen.