2011-06-24 5 views
5

J'ai des fichiers texte de 4 Go + (format csv) et je veux traiter ce fichier en utilisant linq dans C#.Traitement de gros fichier texte en C#

Je lance une requête linq complexe après le chargement de CSV et la conversion en classe?

mais la taille du fichier est 4gb bien que la mémoire de l'application double taille de fichier. Comment puis-je traiter de gros fichiers (linq et nouveau résultat)?

Merci

+0

Qu'est-ce que v ersion de .NET utilisez-vous –

+0

@Rune FS J'utilise .net 4.0 – oguzh4n

Répondre

11

lieu de fichier entier chargement dans la mémoire, vous pouvez lire et traiter la ligne par ligne fichier.

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 vous avez besoin d'exécuter des requêtes complexes par rapport aux données dans le fichier, la bonne chose à faire est de charger les données de base de données et laisser SGBD pour prendre soin des données récupération et gestion de la mémoire.

+1

Qu'en est-il si tout le texte est dans une seule ligne sans retour chariot? – Burimi

+1

@Cody - J'ai supposé que le fichier CSV n'est pas un fichier à une seule ligne. –

+2

Ensuite, vous traiter la ligne entière comme un flux d'octets, plutôt que d'un flux de lignes. –

1

Je pense que celui-ci est une bonne façon ... CSV

+0

[link] (http://i51.tinypic.com/5dphtg.png) problème est ce Lire l'octet 500MB mais la mémoire 2GB – oguzh4n

1

Si vous utilisez .NET 4.0, vous pouvez utiliser Clay puis écrire une méthode qui retourne une ligne IEnumerable pour la ligne et qui fait le code comme ci-dessous possible

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

la méthode pour projeter le CSV dans une séquence d'objets d'argile pourrait être créé comme:

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

merci pour les conseils, J'ai essayé cette solution, mais il est très lent et a même problème de mémoire. – oguzh4n

+0

@ oguzh4n oh je n'ai délibérément pas pris en compte la vitesse puisque vous ne l'avez pas mentionnée dans votre message. Je préférerais la lisibilité (dans ce cas du site d'appel) sur la vitesse n'importe quel jour. A propos des problèmes de mémoire. Si vous pouviez être plus précis sur ceux qu'ils peuvent être fixés. Cela ne doit pas contenir plus d'une ligne du fichier texte et un objet d'argile à la fois (et un peu) alors quelle que soit la mémoire émise le projet ci-dessus, ils peuvent être réparés –

Questions connexes