2011-06-24 30 views
5

Tengo 4GB + archivos de texto (formato csv) y quiero procesar este archivo usando linq en C#.Procesando archivo de texto grande en C#

Ejecuto la consulta compleja de linq después de cargar csv y convertir a la clase?

pero el tamaño del archivo es 4gb aunque la memoria de la aplicación es del doble tamaño del archivo.

¿cómo puedo procesar (linq y nuevo resultado) archivos de gran tamaño?

Gracias

+0

Qué v ersion of .NET está usando –

+0

@Rune FS Estoy usando .net 4.0 – oguzh4n

Respuesta

11

En lugar de cargar todo el archivo en la memoria, se puede leer y procesar la línea por línea del archivo.

using (var streamReader = new StreamReader(fileName)) 
{ 
    string line; 
    while ((line = streamReader.ReadLine()) != null) 
    { 
     // analize line here 
     // throw it away if it does not match 
    } 
} 

[EDIT]

Si necesita ejecutar consultas complejas en contra de los datos en el archivo, lo que hay que hacer es cargar los datos a la base de datos y dejar DBMS para cuidar de datos recuperación y gestión de memoria.

+1

¿Qué tal si todo el texto está en una línea única sin retorno de carro? – Burimi

+1

@Cody - Supuse que el archivo csv no es un solo archivo de línea. –

+2

Luego procesará toda la línea como una secuencia de bytes, en lugar de una secuencia de líneas. –

1

Creo que ésta es una buena manera ... CSV

+0

[link] (http://i51.tinypic.com/5dphtg.png) problema es esto Leer byte 500MB pero memoria 2GB – oguzh4n

1

Si está utilizando .NET 4.0 se podría utilizar Clay y luego escribir un método que devuelve una línea IEnumerable para la línea y eso hace que un código como el siguiente posible

from record in GetRecords("myFile.csv",new []{"Foo","Bar"},new[]{","}) 
where record.Foo == "Baz" 
select new {MyRealBar = int.Parse(record.Bar) 

el método para proyectar la CSV en una secuencia de objetos de arcilla podría crearse como:

private IEnumerable<dynamic> GetRecords(
        string filePath, 
        IEnumerable<string> columnNames, 
        string[] delimiter){ 
      if (!File.Exists(filePath)) 
       yield break; 
      var columns = columnNames.ToArray(); 
      dynamic New = new ClayFactory(); 
      using (var streamReader = new StreamReader(filePath)){ 
       var columnLength = columns.Length; 
       string line; 
       while ((line = streamReader.ReadLine()) != null){ 
        var record = New.Record(); 
        var fields = line.Split(delimiter, StringSplitOptions.None); 
        if(fields.Length != columnLength) 
         throw new InvalidOperationException(
           "fields count does not match column count"); 
        for(int i = 0;i<columnLength;i++){ 
         record[columns[i]] = fields[i]; 
        } 
        yield return record; 
       } 
      } 
     } 
+0

gracias por su consejo, Intenté esta solución pero es muy lenta y tiene el mismo problema de memoria. – oguzh4n

+0

@ oguzh4n oh Delibately no tomé en cuenta la velocidad ya que no mencionó eso en su publicación. Preferiría la legibilidad (en este caso del sitio de llamadas) sobre la velocidad en cualquier día. Acerca de los problemas de memoria. Si pudieras ser más preciso sobre ellos, pueden ser reparados. Esto no tiene que contener más de una línea del archivo de texto y un objeto de arcilla a la vez (y un poco) por lo que cualquier edición de memoria del borrador anterior tiene que pueden ser reparados –

Cuestiones relacionadas