69 Stimmen

Wie man am besten eine Datei in List<string> liest

Ich verwende eine Liste, um die Dateigröße zu begrenzen, da das Ziel eine begrenzte Festplatten- und Speicherkapazität hat. Dies ist, was ich jetzt tue, aber gibt es einen effizienteren Weg?

readonly List<string> LogList = new List<string>();
...
var logFile = File.ReadAllLines(LOG_PATH);
foreach (var s in logFile) LogList.Add(s);

132voto

Evan Mulawski Punkte 53325
var logFile = File.ReadAllLines(LOG_PATH);
var logList = new List<string>(logFile);

Seit logFile ein Array ist, können Sie es an die Funktion List<T> Konstrukteur. Dadurch wird unnötiger Overhead vermieden, wenn über das Array iteriert oder andere IO-Klassen verwendet werden.

Tatsächliche Implementierung des Konstruktors :

public List(IEnumerable<T> collection)
{
        ...
        ICollection<T> c = collection as ICollection<T>;
        if( c != null) {
            int count = c.Count;
            if (count == 0)
            {
                _items = _emptyArray;
            }
            else {
                _items = new T[count];
                c.CopyTo(_items, 0);
                _size = count;
            }
        }   
        ...
}

71voto

Ram Punkte 14350

Eine kleine Aktualisierung der Antwort von Evan Mulawski, um sie kürzer zu machen

List<string> allLinesText = File.ReadAllLines(fileName).ToList()

14voto

Daniel Pryden Punkte 56882

Warum nicht gleich einen Generator verwenden?

private IEnumerable<string> ReadLogLines(string logPath) {
    using(StreamReader reader = File.OpenText(logPath)) {
        string line = "";
        while((line = reader.ReadLine()) != null) {
            yield return line;
        }
    }
}

Dann können Sie sie wie eine Liste verwenden:

var logFile = ReadLogLines(LOG_PATH);
foreach(var s in logFile) {
    // Do whatever you need
}

Natürlich, wenn Sie eine List<string> dann müssen Sie den gesamten Dateiinhalt im Speicher halten. Daran führt eigentlich kein Weg vorbei.

11voto

AmmarTheTrainer Punkte 143

Das kann man einfach so lesen.

List<string> lines = System.IO.File.ReadLines(completePath).ToList();

6voto

Groo Punkte 47623

[Bearbeiten]

Wenn Sie dies tun, um den Anfang einer Protokolldatei zu kürzen, können Sie das Laden der gesamten Datei vermeiden, indem Sie wie folgt vorgehen:

// count the number of lines in the file
int count = 0;
using (var sr = new StreamReader("file.txt"))
{
    while (sr.ReadLine() != null) 
        count++;
}

// skip first (LOG_MAX - count) lines
count = LOG_MAX - count;
using (var sr = new StreamReader("file.txt"))
using (var sw = new StreamWriter("output.txt"))
{
    // skip several lines
    while (count > 0 && sr.ReadLine() != null) 
        count--;

    // continue copying
    string line = "";
    while ((line = sr.ReadLine()) != null)
        sw.WriteLine(line);
}

Zunächst einmal, da File.ReadAllLines lädt die gesamte Datei in ein String-Array ( string[] ), ist das Kopieren in eine Liste überflüssig.

Zweitens: Sie müssen verstehen, dass ein List ist unter der Haube mit einem dynamischen Array implementiert. Dies bedeutet, dass die CLR mehrere Arrays zuweisen und kopieren muss, bis sie die gesamte Datei aufnehmen kann. Da sich die Datei bereits auf der Festplatte befindet, sollten Sie in Erwägung ziehen, Geschwindigkeit gegen Speicher zu tauschen und die Daten direkt auf der Festplatte zu bearbeiten oder sie in kleineren Teilen zu verarbeiten.

  1. Wenn Sie es vollständig in den Speicher laden müssen, versuchen Sie zumindest, es in einem Array zu belassen:

     string[] lines = File.ReadAllLines("file.txt");
  2. Wenn es wirklich eine sein muss List laden Sie die Zeilen nacheinander:

     List<string> lines = new List<string>();
     using (var sr = new StreamReader("file.txt"))
     {
          while (sr.Peek() >= 0)
              lines.Add(sr.ReadLine());
     }

    Nota: List<T> hat einen Konstruktor, der einen Kapazitätsparameter annimmt. Wenn Sie die Anzahl der Zeilen im Voraus kennen, können Sie Mehrfachzuweisungen verhindern, indem Sie das Array im Voraus zuweisen:

     List<string> lines = new List<string>(NUMBER_OF_LINES);
  3. Noch besser ist es, wenn Sie nicht die gesamte Datei im Speicher ablegen, sondern sie "on the fly" verarbeiten:

     using (var sr = new StreamReader("file.txt"))
     {
          string line;
          while ((line = sr.ReadLine()) != null) 
          {
              // process the file line by line
          }
     }

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