Ich muss eine große Datei verarbeiten, etwa 400 KB Zeilen und 200 M. Aber manchmal muss ich von unten nach oben verarbeiten. Wie kann ich hier den Iterator (Yield Return) verwenden? Grundsätzlich lade ich nicht gerne alles in den Speicher. Ich weiß, dass es effizienter ist, Iterator in .NET zu verwenden.
86
Antworten:
Das Rückwärtslesen von Textdateien ist sehr schwierig, es sei denn, Sie verwenden eine Codierung mit fester Größe (z. B. ASCII). Wenn Sie eine Codierung mit variabler Größe haben (z. B. UTF-8), müssen Sie beim Abrufen von Daten immer wieder überprüfen, ob Sie sich in der Mitte eines Zeichens befinden oder nicht.
In das Framework ist nichts eingebaut, und ich vermute, Sie müssten für jede Codierung mit variabler Breite eine separate Hardcodierung durchführen.
EDIT: Dies wurde etwas getestet - aber das heißt nicht, dass es noch keine subtilen Fehler gibt. Es verwendet StreamUtil von MiscUtil, aber ich habe unten nur die notwendige (neue) Methode eingefügt. Oh, und es muss umgestaltet werden - es gibt eine ziemlich umfangreiche Methode, wie Sie sehen werden:
Feedback sehr willkommen. Das hat Spaß gemacht :)
quelle
Sie können File.ReadLines verwenden, um den Zeileniterator abzurufen
BEARBEITEN:
Nachdem ich den Kommentar von applejacks01 gelesen habe, führe ich einige Tests durch und das tut es so aus, als würde
.Reverse()
tatsächlich die gesamte Datei .Früher habe ich
File.ReadLines()
drucken erste Zeile einer 40 MB - Datei - Speichernutzung der Konsolenanwendung war 5MB . Dann wurdeFile.ReadLines().Reverse()
zum Drucken der letzten Zeile derselben Datei verwendet - die Speichernutzung betrug 95 MB .quelle
So erstellen Sie einen Datei-Iterator:
BEARBEITEN:
Dies ist meine feste Version eines Reverse File Readers mit fester Breite:
quelle
Ich habe die Datei Zeile für Zeile in eine Liste eingefügt und dann List.Reverse () verwendet.
...
quelle
Sie können die Datei zeichenweise rückwärts lesen und alle Zeichen zwischenspeichern, bis Sie einen Wagenrücklauf und / oder einen Zeilenvorschub erreichen.
Anschließend kehren Sie die gesammelte Zeichenfolge um und ziehen sie als Linie aus.
quelle
Ich weiß, dass dieser Beitrag sehr alt ist, aber da ich nicht finden konnte, wie ich die am häufigsten gewählte Lösung verwenden kann, habe ich endlich Folgendes gefunden: Hier ist die beste Antwort, die ich mit niedrigen Speicherkosten in VB und C # gefunden habe
http://www.blakepell.com/2010-11-29-backward-file-reader-vb-csharp-source
Hoffe, ich werde anderen dabei helfen, denn ich habe Stunden gebraucht, um diesen Beitrag endlich zu finden!
[Bearbeiten]
Hier ist der c # -Code:
quelle
IDisposable
Felder haben, sollten Sie diese ebenfalls implementierenIDisposable
und ordnungsgemäß entsorgen.Sehr schnelle Lösung für große Dateien . Verwenden Sie das Powershell-Cmdlet Get-Content mit der Option Tail. Das Aufrufen von Powershell bringt ein wenig Overhead mit sich, aber für große Dateien ist es wertlos
Erforderliche PowerShell-Referenz
quelle
Ich füge auch meine Lösung hinzu. Nachdem ich einige Antworten gelesen hatte, passte nichts wirklich zu meinem Fall. Ich lese Byte für Byte von hinten, bis ich ein LineFeed finde, und speichere dann die gesammelten Bytes als Zeichenfolge, ohne Pufferung zu verwenden .
Verwendung:
Implementierung:
quelle
Ich wollte das Gleiche tun. Hier ist mein Code. Diese Klasse erstellt temporäre Dateien, die Teile der großen Datei enthalten. Dadurch wird ein Aufblähen des Speichers vermieden. Der Benutzer kann angeben, ob die Datei umgekehrt werden soll. Dementsprechend wird der Inhalt in umgekehrter Weise zurückgegeben.
Diese Klasse kann auch verwendet werden, um große Datenmengen in eine einzelne Datei zu schreiben, ohne den Speicher aufzublähen.
Bitte geben Sie Feedback.
Dieser Dienst kann wie folgt genutzt werden:
quelle
Hier gibt es bereits gute Antworten, und hier ist eine weitere LINQ-kompatible Klasse, die Sie verwenden können und die sich auf die Leistung und Unterstützung großer Dateien konzentriert. Es wird ein Zeilenabschluss "\ r \ n" angenommen.
Verwendung :
ReverseTextReader Klasse :
quelle
Falls jemand anderes darauf stößt, habe ich es mit dem folgenden PowerShell-Skript gelöst, das mit geringem Aufwand leicht in ein C # -Skript geändert werden kann.
Dies beginnt im Wesentlichen mit dem Lesen der letzten 10.000 Zeichen einer Datei und gibt jede Zeile aus.
quelle
.Seek(-10000, [System.IO.SeekOrigin]::End);
?