6
votes

Recherche de plusieurs chaînes dans plusieurs fichiers

J'ai un fichier texte contenant 21 000 chaînes (une ligne chacune) et 500 Mo d'autres fichiers texte (codes source maily). Pour chaque chaîne, je dois déterminer si elle est contenue dans l'un de ces fichiers. J'ai écrit un programme qui fait le travail mais sa performance est terrible (cela ferait cela dans quelques jours, j'ai besoin de faire le travail en 5-6 heures maximum).
J'écris avec C #, Visual Studio 2010

J'ai quelques questions concernant mon problème:
a) Quelle approche est la meilleure? p> xxx pré>

ou p>

StreamReader r = new StreamReader(file);
string s = r.ReadToEnd();
//if(s.Contains(xxx));


4 commentaires

Devez-vous écrire le programme? Windows a FindStr intégré. Vous pouvez utiliser une boucle pour pouvoir rechercher ces autres fichiers en parallèle


Certainement pas une réponse correcte / complète, mais ne chargez pas tous les fichiers (500 Mo!) Pour chaque chaîne. Une fois que vous avez (une partie de) le fichier en mémoire, faites toutes vos actions alors.


Je voulais charger un fichier entier un par un, pas 500 Mo de fichiers à la fois.


Dans quel système d'exploitation êtes-vous sur vous, si vous êtes sur Win7, vous pouvez rechercher automatiquement dans les fichiers et son assez rapide.


5 Réponses :


4
votes

Vous voulez minimiser les fichiers I / O, votre première idée est donc très mauvaise, car vous ouvriez les "autres" fichiers jusqu'à 21 000 fois. Vous voulez utiliser quelque chose en fonction du second (A1). Et quand ces autres fichiers ne sont pas trop gros, chargez-les en mémoire une fois avec ReadallText.

List<string> keys = ...;    // load all strings

foreach(string f in Files)
{
    //search for each string that is not already found
    string text = System.IO.File.ReadAllText(f);  //easy version of ReadToEnd


    // brute force
    foreach(string key in keyes)
    {
        if (text.IndexOf(key) >= 0) ....
    }

}


2 commentaires

Est si (text.indexof (clé)> = 0) plus vite que si (texte.contains (clé))?


@Ichi: Non, je m'attendrais à ce qu'ils soient aussi rapides.



2
votes

Vous voudrez peut-être regarder la recherche Windows SDK ici

http://msdn.microsoft.com/ EN-US / Bibliothèque / AA965362% 28VS.85% 29.aspx


0 commentaires

2
votes
  1. à la fois a) et b), la deuxième option est efficace
  2. Le threading peut ne pas améliorer la performance CoZ Chaque thread lirait le fichier de votre disque, de sorte que votre disque deviendra un goulot d'étranglement.
  3. SRY Je n'ai aucune idée de S / W pour votre objectif

    extrait de fil xxx

    Directives générales d'E / S

    Quels sont quelques recommandations de base pour réduire le I / O activité de votre programme et améliorant ainsi ses performances. Comme pour toutes les recommandations, il est important de mesurer la performance du code optimisée avant et après l'optimisation afin de s'assurer qu'elle devient plus rapide.

    1. minimiser le nombre de fichiers Opérations que vous effectuez
    2. groupe plusieurs petits transferts d'E / S dans un grand transfert. Un seul écrire de huit pages est plus rapide que huit écritures simples séparées écrites, principalement parce qu'il permet le dur disque pour écrire les données en un seul passage sur la surface du disque. Pour plus Informations,
    3. effectuer des lectures séquentielles au lieu de cherchant et lire de petits blocs de Les données. Le noyau de manière transparente clusters les opérations d'E / S, qui fait Séquentiel lit beaucoup plus vite.
    4. Évitez de sauter à l'avance dans un vide fichier avant d'écrire des données. Le système doit écrire des zéros dans le espace intermédiaire pour combler l'écart. Pour plus d'informations, voir Lecture est généralement moins cher que d'écrire Données.
    5. reporter toutes les opérations d'E / S jusqu'à la pointez que votre application réellement a besoin des données.
    6. Utilisez le système Préférences pour capturer uniquement les préférences des utilisateurs (telle comme position de fenêtre et vue paramètres) et pas de données pouvant être Recommandé à moindre coût.
    7. Ne présumez pas que la mise en cache des données de fichier en mémoire accélérera votre application. Stocker les données de fichier dans la mémoire améliore la vitesse jusqu'à ce que la mémoire est échangée sur le disque, à quel point vous payez le prix pour accéder à nouveau au disque. S'efforcer de trouver un approprié équilibre entre lire du disque et mise en cache en mémoire

0 commentaires

6
votes

Si vous voulez simplement savoir si la chaîne est trouvée ou non trouvée et que vous n'avez pas besoin de faire un traitement supplémentaire, je vous suggérerais que vous n'utilisez que Grep. Grep est extrêmement rapide et conçu pour exactement ce genre de problème.

grep -f strings-file other-files...


3 commentaires

Oui, malgré la balise [C #], cela pourrait être la meilleure approche.


Je ne connais pas avec Grep et comment cela fonctionne alors peut-être que peu d'aide comment utiliser cela?


Grep est un outil très courant dans * Nix Systems. Il y a beaucoup de documents là-bas, donc il y a tenu d'être un bon tutoriel quelque part. La commande suggérée cherche toutes les chaînes trouvées dans "Strings-File" dans n'importe lequel des "autres fichiers" et imprime toutes les lignes de correspondance dans "Autres fichiers". Il existe de nombreuses options pour changer la sortie sur ce dont vous avez besoin.



2
votes

La recherche doit-elle être en temps réel sur 500 Mo de texte actuel? La raison pour laquelle je demande est parce que vous pouvez créer un index de recherche sur les fichiers texte et effectuer la recherche. Ce serait beaucoup plus rapide ... Jetez un coup d'œil à Lucene

lucene.net

C # et Lucene à indexer et à rechercher


2 commentaires

Il n'a pas besoin d'être une recherche en temps réel. C'est une tâche unique. Faire et oublier ça: p


Ensuite, utilisez Lucene (je n'ai pas utilisé Windows Search SDK) pour construire un index de recherche complet et effectuer des recherches contre elle ... J'ai utilisé Lucene avant ... c'est rapide!