2010-10-13 8 views
1

Supposons que vous souhaitiez écrire une application traitant plusieurs fichiers texte, fournis en tant qu'arguments sur la ligne de commande (par exemple MyProcessor file1 file2 ...). C'est une tâche très courante pour laquelle Perl est souvent utilisé, mais que se passe-t-il si l'on veut profiter directement de .NET et utiliser C#. Quel est le code de plaque de chaudière d'application C# 4.0 le plus simple qui vous permet de faire cela? Il devrait inclure le traitement ligne par ligne de chaque ligne de chaque fichier et faire quelque chose avec cette ligne, en appelant une fonction pour le traiter ou peut-être une meilleure façon de faire ce genre de traitement de ligne "group" (par exemple, LINQ ou une autre méthode).Traitement de plusieurs fichiers texte C#

+0

Je pense que vous essayez de trop compliquer les choses. Il suffit de plonger et de commencer à écrire votre code, d'ajouter une logique «framework» lorsque la complexité l'exige, et non plus tôt. – Juliet

+0

Allez-vous passer le chemin du fichier dans les arguments de la ligne de commande? – TalentTuner

Répondre

9

Vous pouvez traiter les fichiers en parallèle par la lecture de chaque ligne et le passage à une fonction de traitement:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Parallel.ForEach(args, file => 
     { 
      using (var stream = File.OpenRead(file)) 
      using (var reader = new StreamReader(stream)) 
      { 
       string line; 
       while ((line = reader.ReadLine()) != null) 
       { 
        ProcessLine(line); 
       } 
      } 
     }); 
    } 

    static void ProcessLine(string line) 
    { 
     // TODO: process the line 
    } 
} 

Maintenant, il suffit d'appeler: SomeApp.exe file1 file2 file3

Avantages de cette approche:

  • Les fichiers sont traités en parallèle => en tirant parti de plusieurs cœurs de processeur
  • Les fichiers sont lus ligne par ligne et que la ligne actuelle est maintenue en mémoire ce qui réduit la consommation de mémoire et vous permet de travailler avec de gros fichiers
+0

Une solution très intéressante je dois dire. Je suppose que rendre le traitement non parallèle ne serait pas trop dur non plus? –

+0

+1 Pour utiliser le dernier concept Parallel – TalentTuner

+1

@Michael: Il suffit d'échanger le Parallel.ForEach avec une boucle foreach standard ... –

2

Simple;



foreach(var f in args) 
{ 
    var filecontent = File.ReadToEnd(); 
    //Logic goes here 
} 

+0

Avez-vous déjà raison ce code? et à quoi cela résout-il – TalentTuner

+0

résoudre le problème de la lecture de plusieurs fichiers, où leur chemin a été passé à travers les arguments –

+0

Malheureusement, ReadToEnd chargera le fichier entier en mémoire. Cela est prohibitif pour les gros fichiers. La clé ici est de traiter efficacement le fichier une ligne à la fois, indépendamment de la taille du fichier. –

2

Après beaucoup expérimenter, changer cette ligne dans la réponse de Darin Dimitrov:

using (var stream = File.OpenRead(file)) 

à:

using (var stream=new FileStream(file,System.IO.FileMode.Open, 
           System.IO.FileAccess.Read, 
           System.IO.FileShare.ReadWrite, 
           65536)) 

pour changer la taille de la mémoire tampon de lecture à partir de la valeur par défaut de 4 Ko à 64 Ko peuvent raser jusqu'à 10% de réduction du temps de lecture du fichier w hen lit "line at a time" via un lecteur de flux, surtout si le fichier texte est grand. Les tailles de mémoire tampon plus importantes ne semblent pas améliorer davantage les performances.

Cette amélioration est présente, même lors de la lecture à partir d'un SSD relativement rapide. Les économies sont encore plus substantielles si un HD ordinaire est utilisé. Fait intéressant, vous obtenez cette amélioration significative des performances même si le fichier est déjà mis en cache par le système d'exploitation (Windows 7/2008R2), ce qui est quelque peu contre-intuitif.