La mejor manera de leer un archivo en la Lista


Estoy usando una lista para limitar el tamaño del archivo ya que el objetivo está limitado en disco y ram. Esto es lo que estoy haciendo ahora, pero hay una manera más eficiente?

readonly List<string> LogList = new List<string>();
...
var logFile = File.ReadAllLines(LOG_PATH);
foreach (var s in logFile) LogList.Add(s);
Author: jacknad, 2011-08-02

8 answers

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

Dado que logFile es un array, puedes pasarlo al constructor List<T>. Esto elimina la sobrecarga innecesaria cuando se itera sobre la matriz, o el uso de otros IO clases.

Implementación actual del constructor :

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;
            }
        }   
        ...
} 
 88
Author: Evan Mulawski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-10 02:05:16

Una pequeña actualización de la respuesta de Evan Mulawski para hacerla más corta

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

 37
Author: Rama,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-14 00:04:09

¿Por qué no usar un generador en su lugar?

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

Entonces puedes usarlo como usarías la lista:

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

Por supuesto, si necesita tener un List<string>, entonces tendrá que mantener todo el contenido del archivo en memoria. No hay manera de evitarlo.

 13
Author: Daniel Pryden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-01 21:11:17

No lo guarde si es posible. Solo léelo si tienes problemas de memoria. Puedes usar un StreamReader:

using (var reader = new StreamReader("file.txt"))
{
    var line = reader.ReadLine();
    // process line here
}

Esto se puede envolver en un método que produce cadenas por línea leída si desea usar LINQ.

 5
Author: Deleted,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-01 21:04:53

[Editar]

Si está haciendo esto para recortar el comienzo de un archivo de registro, puede evitar cargar el archivo completo haciendo algo como esto:

// 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);
}

En primer lugar, dado que File.ReadAllLines carga todo el archivo en una matriz de cadenas (string[]), copiar a una lista es redundante.

En segundo lugar, debe entender que un List se implementa usando una matriz dinámica debajo del capó. Esto significa que CLR tendrá que asignar y copiar varios arrays hasta que pueda acomodar todo el archivo. Dado que el archivo ya está en el disco, puede considerar la velocidad de intercambio de memoria y trabajar directamente en los datos del disco, o procesarlos en trozos más pequeños.

  1. Si necesita cargarlo completamente en memoria, al menos intente dejarlo en una matriz:

     string[] lines = File.ReadAllLines("file.txt");
    
  2. Si realmente necesita ser un List, cargue las líneas una por una:

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

    Nota: List<T> tiene un constructor que acepta un parámetro de capacidad. Si usted sabe el número de líneas por adelantado, puede evitar asignaciones múltiples mediante la preasignación de la matriz por adelantado:

     List<string> lines = new List<string>(NUMBER_OF_LINES);
    
  3. Aún mejor, evite almacenar todo el archivo en memoria y procesarlo "sobre la marcha":

     using (var sr = new StreamReader("file.txt"))
     {
          string line;
          while (line = sr.ReadLine() != null) 
          {
              // process the file line by line
          }
     }
    
 5
Author: Groo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-01 21:27:02
//this is only good in .NET 4
//read your file:
List<string> ReadFile = File.ReadAllLines(@"C:\TEMP\FILE.TXT").ToList();

//manipulate data here
foreach(string line in ReadFile)
{
    //do something here
}

//write back to your file:
File.WriteAllLines(@"C:\TEMP\FILE2.TXT", ReadFile);
 2
Author: User2325641,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-14 16:55:19
List<string> lines = new List<string>();
 using (var sr = new StreamReader("file.txt"))
 {
      while (sr.Peek() >= 0)
          lines.Add(sr.ReadLine());
 }

Yo sugeriría esto... de la respuesta de Groo.

 1
Author: Amit Ranjan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-01 21:14:52
string inLine = reader.ReadToEnd();
myList = inLine.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();

También uso el Entorno.Nueva línea.toCharArray también, pero encontré que no funcionó en un par de archivos que terminaron en \r\n. Pruebe cualquiera de los dos y espero que funcione bien para usted.

 0
Author: vSteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-21 18:16:29