404 Stimmen

Was ist der schnellste Weg, eine Textdatei zeilenweise zu lesen?

Ich möchte eine Textdatei Zeile für Zeile lesen. Ich wollte wissen, ob ich es so effizient wie möglich innerhalb der .NET C# Umfang der Dinge zu tun.

Das ist es, was ich bis jetzt versucht habe:

var filestream = new System.IO.FileStream(textFilePath,
                                          System.IO.FileMode.Open,
                                          System.IO.FileAccess.Read,
                                          System.IO.FileShare.ReadWrite);
var file = new System.IO.StreamReader(filestream, System.Text.Encoding.UTF8, true, 128);

while ((lineOfText = file.ReadLine()) != null)
{
    //Do something with the lineOfText
}

421voto

Martin Liversage Punkte 100306

Um den schnellsten Weg zu finden, eine Datei Zeile für Zeile zu lesen, müssen Sie einige Vergleiche anstellen. Ich habe einige kleine Tests auf meinem Computer durchgeführt, aber Sie können nicht erwarten, dass meine Ergebnisse auf Ihre Umgebung zutreffen.

Verwendung von StreamReader.ReadLine

Das ist im Grunde Ihre Methode. Aus irgendeinem Grund setzen Sie die Puffergröße auf den kleinstmöglichen Wert (128). Wenn Sie diesen Wert erhöhen, wird die Leistung im Allgemeinen gesteigert. Die Standardgröße ist 1.024 und andere gute Wahlmöglichkeiten sind 512 (die Sektorgröße in Windows) oder 4.096 (die Clustergröße in NTFS). Um die optimale Puffergröße zu ermitteln, müssen Sie einen Benchmark-Test durchführen. Ein größerer Puffer ist - wenn nicht schneller - so doch zumindest nicht langsamer als ein kleinerer Puffer.

const Int32 BufferSize = 128;
using (var fileStream = File.OpenRead(fileName))
  using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize)) {
    String line;
    while ((line = streamReader.ReadLine()) != null)
    {
      // Process line
    }
  }

Le site FileStream Konstruktor können Sie angeben FileOptions . Wenn Sie beispielsweise eine große Datei sequentiell von Anfang bis Ende lesen, können Sie von folgenden Vorteilen profitieren FileOptions.SequentialScan . Auch hier ist ein Benchmarking das Beste, was Sie tun können.

File.ReadLines verwenden

Diese Lösung ist Ihrer eigenen sehr ähnlich, außer dass sie mit einer StreamReader mit einer festen Puffergröße von 1.024. Auf meinem Computer führt dies zu einer etwas besseren Leistung als Ihr Code mit der Puffergröße von 128. Sie können jedoch die gleiche Leistungssteigerung erzielen, wenn Sie eine größere Puffergröße verwenden. Diese Methode ist mit einem Iteratorblock implementiert und verbraucht nicht für alle Zeilen Speicher.

var lines = File.ReadLines(fileName);
foreach (var line in lines)
  // Process line

File.ReadAllLines verwenden

Diese Methode ähnelt der vorhergehenden, mit dem Unterschied, dass sie eine Liste von Zeichenketten anlegt, die zur Erstellung des zurückgegebenen Zeilenarrays verwendet wird, so dass der Speicherbedarf höher ist. Sie gibt jedoch zurück String[] und nicht ein IEnumerable<String> die es Ihnen ermöglichen, die Zeilen nach dem Zufallsprinzip aufzurufen.

var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i += 1) {
  var line = lines[i];
  // Process line
}

String.Split verwenden

Diese Methode ist erheblich langsamer, zumindest bei großen Dateien (getestet mit einer 511 KB großen Datei), was wahrscheinlich darauf zurückzuführen ist, wie String.Split umgesetzt wird. Außerdem wird ein Array für alle Zeilen zugewiesen, was den Speicherbedarf im Vergleich zu Ihrer Lösung erhöht.

using (var streamReader = File.OpenText(fileName)) {
  var lines = streamReader.ReadToEnd().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
  foreach (var line in lines)
    // Process line
}

Mein Vorschlag ist die Verwendung von File.ReadLines weil es sauber und effizient ist. Wenn Sie spezielle Freigabeoptionen benötigen (z. B. wenn Sie FileShare.ReadWrite ), können Sie Ihren eigenen Code verwenden, aber Sie sollten die Puffergröße erhöhen.

217voto

Jon Skeet Punkte 1325502

Wenn Sie .NET 4 verwenden, benutzen Sie einfach File.ReadLines die alles für Sie erledigt. Ich vermute, es ist viel die gleiche wie die Ihre, außer dass sie auch die FileOptions.SequentialScan und einen größeren Puffer (128 erscheint sehr klein).

45voto

Free Coder 24 Punkte 873

Während File.ReadAllLines() ist eine der einfachsten Möglichkeiten, eine Datei zu lesen, aber auch eine der langsamsten.

Wenn Sie nur Zeilen in einer Datei lesen wollen, ohne viel zu tun, nach diesen Maßstäben Der schnellste Weg, eine Datei zu lesen, ist die uralte Methode der:

using (StreamReader sr = File.OpenText(fileName))
{
        string s = String.Empty;
        while ((s = sr.ReadLine()) != null)
        {
               //do minimal amount of work here
        }
}

Wenn Sie jedoch viel mit jeder Zeile machen müssen, sollten Sie 本論文 kommt zu dem Schluss, dass der beste Weg der folgende ist (und es ist schneller, einen string[] im Voraus zuzuweisen, wenn man weiß, wie viele Zeilen man lesen will) :

AllLines = new string[MAX]; //only allocate memory here

using (StreamReader sr = File.OpenText(fileName))
{
        int x = 0;
        while (!sr.EndOfStream)
        {
               AllLines[x] = sr.ReadLine();
               x += 1;
        }
} //Finished. Close the file

//Now parallel process each line in the file
Parallel.For(0, AllLines.Length, x =>
{
    DoYourStuff(AllLines[x]); //do your work here
});

19voto

user2671536 Punkte 209

Verwenden Sie den folgenden Code:

foreach (string line in File.ReadAllLines(fileName))

Das war ein RIESIGER Unterschied in der Leseleistung.

Das geht zwar auf Kosten des Speicherverbrauchs, aber das ist es allemal wert!

8voto

Saeed Amiri Punkte 21834

Wenn die Datei nicht sehr groß ist, ist es schneller, die gesamte Datei zu lesen und sie anschließend aufzuteilen.

var filestreams = sr.ReadToEnd().Split(Environment.NewLine, 
                              StringSplitOptions.RemoveEmptyEntries);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X