Ich möchte eine Textdatei Zeile für Zeile lesen. Ich wollte wissen, ob ich es im Rahmen von .NET C # so effizient wie möglich mache.
Das versuche ich bisher:
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
}
c#
.net
performance
file-io
text-files
Loren C Fortner
quelle
quelle
Fastest
meinen Sie aus Leistungs- oder Entwicklungsperspektive?filestream = new FileStream
inusing()
Anweisung zu vermeiden mögliche lästige Probleme mit gesperrter Datei GriffAntworten:
Um den schnellsten Weg zu finden, eine Datei Zeile für Zeile zu lesen, müssen Sie ein Benchmarking durchführen. Ich habe einige kleine Tests auf meinem Computer durchgeführt, aber Sie können nicht erwarten, dass meine Ergebnisse für Ihre Umgebung gelten.
Verwenden von StreamReader.ReadLine
Dies ist im Grunde Ihre Methode. Aus irgendeinem Grund setzen Sie die Puffergröße auf den kleinstmöglichen Wert (128). Wenn Sie dies erhöhen, wird die Leistung im Allgemeinen erhöht. Die Standardgröße ist 1.024 und andere gute Optionen sind 512 (die Sektorgröße in Windows) oder 4.096 (die Clustergröße in NTFS). Sie müssen einen Benchmark ausführen, um eine optimale Puffergröße zu ermitteln. Ein größerer Puffer ist - wenn nicht schneller - zumindest nicht langsamer als ein kleinerer Puffer.
Mit dem
FileStream
Konstruktor können Sie FileOptions angeben . Wenn Sie beispielsweise eine große Datei nacheinander von Anfang bis Ende lesen, können Sie davon profitierenFileOptions.SequentialScan
. Auch hier ist Benchmarking das Beste, was Sie tun können.Verwenden von File.ReadLines
Dies ist Ihrer eigenen Lösung sehr ähnlich, außer dass sie
StreamReader
mit einer festen Puffergröße von 1.024 implementiert wird . Auf meinem Computer führt dies zu einer etwas besseren Leistung im Vergleich zu Ihrem Code mit der Puffergröße von 128. Sie können jedoch die gleiche Leistungssteigerung erzielen, indem Sie eine größere Puffergröße verwenden. Diese Methode wird mithilfe eines Iteratorblocks implementiert und belegt nicht für alle Zeilen Speicher.Verwenden von File.ReadAllLines
Dies ist der vorherigen Methode sehr ähnlich, außer dass diese Methode eine Liste von Zeichenfolgen erstellt, die zum Erstellen des zurückgegebenen Zeilenarrays verwendet werden, sodass die Speicheranforderungen höher sind. Es wird jedoch zurückgegeben und Sie können
String[]
nichtIEnumerable<String>
zufällig auf die Zeilen zugreifen.Verwenden von String.Split
Diese Methode ist erheblich langsamer, zumindest bei großen Dateien (getestet an einer 511-KB-Datei), wahrscheinlich aufgrund der
String.Split
Implementierung. Außerdem wird allen Zeilen ein Array zugewiesen, wodurch der im Vergleich zu Ihrer Lösung erforderliche Speicher erhöht wird.Mein Vorschlag ist zu verwenden,
File.ReadLines
weil es sauber und effizient ist. Wenn Sie spezielle Freigabeoptionen benötigen (z. B. verwendenFileShare.ReadWrite
), können Sie Ihren eigenen Code verwenden, aber Sie sollten die Puffergröße erhöhen.quelle
Wenn Sie .NET 4 verwenden, verwenden Sie einfach,
File.ReadLines
was alles für Sie erledigt. Ich vermute, es ist fast dasselbe wie deins, außer dass es auchFileOptions.SequentialScan
einen größeren Puffer verwenden kann (128 scheint sehr klein zu sein).quelle
ReadLines()
ist, dass es faul ist und daher gut mit LINQ funktioniert.Dies
File.ReadAllLines()
ist eine der einfachsten Möglichkeiten zum Lesen einer Datei, aber auch eine der langsamsten.Wenn Sie nur Zeilen in einer Datei lesen möchten, ohne viel zu tun, ist nach diesen Benchmarks der schnellste Weg, eine Datei zu lesen, die uralte Methode von:
Wenn Sie jedoch mit jeder Zeile viel tun müssen, kommt dieser Artikel zu dem Schluss, dass der beste Weg der folgende ist (und es ist schneller, eine Zeichenfolge [] vorab zuzuweisen, wenn Sie wissen, wie viele Zeilen Sie lesen werden):
quelle
Verwenden Sie den folgenden Code:
Dies war ein großer Unterschied in der Leseleistung.
Es geht zu Lasten des Speicherverbrauchs, ist es aber absolut wert!
quelle
File.ReadAllLines
In der Frage zum Stapelüberlauf gibt es ein gutes Thema dazu. Ist die Rendite langsamer als die Rendite der alten Schule? .
Es sagt:
quelle
Wenn die Dateigröße nicht groß ist, ist es schneller, die gesamte Datei zu lesen und anschließend zu teilen
quelle
File.ReadAllLines()
File.ReadAllLines
dass eine feste Puffergröße haben, da die Dateigröße bekannt ist.File.ReadAllLines
wird eine Liste erstellt und in einer Schleife mitStreamReader.ReadLine
(mit möglicher Neuzuweisung des zugrunde liegenden Arrays) zu dieser Liste hinzugefügt . Diese Methode verwendet eine Standardpuffergröße von 1024. Dadurch wirdStreamReader.ReadToEnd
der Zeilenanalyse-Teil vermieden und die Puffergröße kann bei Bedarf im Konstruktor festgelegt werden.Wenn Sie über genügend Speicher verfügen, habe ich einige Leistungssteigerungen festgestellt, indem ich die gesamte Datei in einen Speicherstrom eingelesen und daraufhin einen Stream-Reader geöffnet habe, um die Zeilen zu lesen. Solange Sie tatsächlich vorhaben, die gesamte Datei zu lesen, kann dies zu Verbesserungen führen.
quelle
File.ReadAllLines
scheint dann eine bessere Wahl zu sein.Sie können nicht schneller werden, wenn Sie eine vorhandene API zum Lesen der Zeilen verwenden möchten. Das Lesen größerer Blöcke und das manuelle Finden jeder neuen Zeile im Lesepuffer wäre jedoch wahrscheinlich schneller.
quelle