Ich habe eine Textdatei mit mehr als 3000 Zeilen. Ich finde die Anzahl der Zeilen mit
%Vor%Dann erzeuge ich eine Zufallszahl
%Vor%Jetzt muss ich die spezifische Zeile lesen, die von der Zufallszahl erzeugt wird. Ich kann dies mit
tun %Vor%Da meine Datei groß ist, glaube ich nicht, dass die Erstellung eines so großen Arrays effizient ist. Gibt es einen effizienteren oder einfacheren Weg, dies zu tun?
Hier ist eine Lösung, die die Datei zweimal wiederholt (erstes Mal, um Zeilen zu zählen, nächstes Mal, um Zeile auszuwählen). Der Vorteil ist, dass Sie kein Array mit 3000 Strings im Speicher erstellen müssen. Aber, wie oben erwähnt, wird möglicherweise langsamer sein. Warum möglicherweise? - Weil File.ReadAllLines
eine Liste von Zeichenfolgen innerhalb erstellt und diese Liste wird viele Male geändert, während sie mit 3000 Elementen gefüllt wird. (Die Anfangskapazität ist 4
. Wenn das innere Array vollständig gefüllt ist, wird das neue Array der doppelten Größe erstellt und alle Strings werden dorthin kopiert).
Also verwendet die Lösung die Methode File.ReadLines
, die IEnumerable<string>
mit Zeilen zurückgibt, die Sie nicht brauchen:
BTW, intern verwendet File.ReadLines
SteamReader
, das die Datei zeilenweise liest.
Sie können die Datei analysieren, um den Index jeder Zeile zu finden, und zu einem späteren Zeitpunkt können Sie zu einer bestimmten Zeile zurückkehren, indem Sie Stream.Position verwenden, um den Inhalt abzurufen. Mit dieser Methode müssen Sie nichts im Speicher behalten und es ist ziemlich schnell. Ich habe dies an einer Datei getestet, die 20 KB Zeilen und 1 MB groß ist . Es dauerte 7ms, um die Datei zu indizieren und 0.3, um die Zeile zu erhalten.
%Vor%Sie können Ihren Stream in StreamReader einbinden und ReadLine so oft wie nötig aufrufen, um zu Ihrer Zielleitung zu gelangen. Auf diese Weise müssen Sie nicht den gesamten Dateiinhalt im Speicher halten.
Das ist jedoch nur möglich, wenn Sie das selten tun und die Datei ziemlich groß ist.
Verwenden Sie Reservoir Sampling , um dies in einem einzigen Durchlauf zu lösen
Wenn Sie nach dem Zufallsprinzip ein oder mehrere Elemente aus einer Liste von Elementen auswählen möchten, für die die Länge dieser Liste nicht im Voraus bekannt ist, können Sie Reservoir Sampling .
Wir können davon profitieren, zusammen mit der File.ReadLines()
-Methode (die vermeidet Pufferung aller Zeilen im Speicher), um einen Single-Pass-Algorithmus zu schreiben, der jede Zeile nur einmal ohne Pufferung liest.
Der folgende Beispielcode zeigt eine verallgemeinerte Lösung, mit der Sie eine beliebige Anzahl von Zeilen nach dem Zufallsprinzip auswählen können. Für Ihren Fall ist N = 1.
Der Beispielcode enthält auch ein Testprogramm, um nachzuweisen, dass die Zeilen zufällig mit einer einheitlichen Verteilung ausgewählt wurden.
(Um zu sehen, wie dieser Code funktioniert, siehe den Wiki-Artikel, den ich oben verlinkt habe.)
%Vor%Unten wird Ihnen das Lesen einer bestimmten Zeile in einer Datei helfen.
Ein Code-Snipet
%Vor%Diese können auch hilfreich sein ..
Wie lese ich ein angegebene Zeile in einer Textdatei?
Und unten ist zum Bearbeiten
Bearbeiten Sie eine bestimmte Zeile eines Textes Datei in C #
Ich hoffe, es hilft ...
Tags und Links c#