2010-11-24 17 views
2

Mon programme va dans un répertoire et recherche des fichiers pdf pour les analyser. Ce programme est toujours en cours d'exécution, donc je dois m'assurer de ne pas analyser à nouveau le même fichier.en boucle pour les fichiers PDF

J'ai utilisé une liste pour stocker les noms de fichiers et ensuite vérifier s'ils sont là.

Mon code ne fonctionne pas à cet égard, si quelqu'un peut jeter un oeil et voir ce qui est faux, il serait grandement apprécié.

FileInfo[] filePaths = di.GetFiles("*.pdf"); 
for (int i = 0; i < filePaths.Length; i++) 
{ 
    foreach (string fileName in usedFileNames) 
    { 
     if (fileName.Equals(filePaths[i].Name)) 
     { 
      isInList = true; 
     } 
     else 
     { 
      isInList = false; 
     } 
    } 
    if (isInList == false) 
    { 
     PDFReaderChooser chooser = new PDFReaderChooser(filePaths[i].Name); 
     usedFileNames.Add(filePaths[i].Name); 
    } 

} 
+0

Votre code ne fonctionne pas car vous devez insérer une instruction break après "isInList = true;". –

+0

@ AS-CII: cela n'a aucun sens, car il teste 'isInList == false' plus tard; il y a effectivement rupture ... – Domenic

+0

Oui mais à chaque fois que la boucle s'exécute, la variable isInList est mise à jour également si un nom de fichier est trouvé. Exemple: # 1 - Égal, isInList = true; # 2 - NotEqual, isInList = false. Dans ce cas, la dernière valeur que la variable suppose est fausse et donc le résultat est complètement faux. Si vous ne me faites pas confiance, testez le code vous-même :) Une alternative pourrait également être de supprimer l'instruction else. –

Répondre

0

Essayez ceci:

FileInfo[] filePaths = di.GetFiles("*.pdf"); 
foreach(FileInfo fInfo in filePaths) 
{ 
    if (!usedFileNames.Contains(fInfo.Name)) 
    { 
     PDFReaderChooser chooser = new PDFReaderChooser(fInfo.Name); 
     usedFileNames.Add(fInfo.Name); 
    } 
} 

Comme je l'ai commenté votre question, le code affiché ne fonctionne pas parce que vous devez insérer une instruction break, comme ceci:

for (int i = 0; i < filePaths.Length; i++) 
{ 
    bool isInList = false; 

    foreach (string fileName in usedFileNames) 
    { 
     if (fileName.Equals(filePaths[i].Name)) 
      isInList = true; 
    } 

    if (isInList == false) 
    { 
     Console.WriteLine("Not in list! #{0}", x); 
     usedFileNames.Add(filePaths[i].Name); 
    } 
} 

Quoi qu'il en soit, je vous recommande d'utiliser l'une des techniques présentées dans cette question réponses.

+0

Puis-je suggérer un 'foreach'? – Domenic

+0

Eh bien, je n'avais pas changé le code parce qu'il devait peut-être utiliser le compteur. De toute façon je le répare. Merci :) –

0

A LINQ Contient opération ferait autant plus concise (en supposant usedFileNames est un List<string>):

FileInfo[] filePaths = di.GetFiles("*.pdf"); 
foreach(FileInfo myInfo in filePaths) 
{ 
    if (!usedFileNames.Contains(myInfo.Name)) 
    { 
     PDFReaderChooser chooser = new PDFReaderChooser(myInfo.Name); 
     usedFileNames.Add(myInfo.Name); 
    } 

} 
4

Plus concise encore:

var fileNames = di.GetFiles("*.pdf") 
        .Select(f => f.Name) 
        .Where(n => !usedFileNames.Contains(n)); 
usedFileNames.AddRange(fileNames); 

foreach (var fileName in fileNames) 
{ 
    var chooser = new PDFReaderChooser(fileName); 
} 

Ce abstracts bien loin la logique qui figure sur laquelle les noms de fichiers que vous devez traiter (en dehors de la boucle), à ​​partir de la logique qui les traite (à l'intérieur de la boucle).

+0

lol que j'écrivais juste ceci. 2 secondes trop lent je suppose. +1 – Kelly

+0

Haha qui me fait me sentir mieux sur mon propre "deux secondes deux lent" sur une autre question il y a dix minutes: D – Domenic

3

Alors que les autres réponses sont de meilleures solutions au problème, elles n'expliquent pas pourquoi le code original n'a pas fonctionné. Le problème est que l'algorithme écrase la valeur de la variable isInList, qui ne sera donc vraie que pour le dernier fichier de la liste. Cela fixerait ce problème:

FileInfo[] filePaths = di.GetFiles("*.pdf"); 
for (int i = 0; i < filePaths.Length; i++) 
{ 
    isInList = false 
    foreach (string fileName in usedFileNames) 
    { 
     if (fileName.Equals(filePaths[i].Name)) 
     { 
      isInList = true; 
      break; 
     } 
    } 
    if (isInList == false) 
    { 
     PDFReaderChooser chooser = new PDFReaderChooser(filePaths[i].Name); 
     usedFileNames.Add(filePaths[i].Name); 
    } 
} 

Je voudrais ajouter qu'il est préférable d'utiliser un HashSet au lieu d'une liste pour votre collection usedFileNames. L'ensemble de hachage est conçu pour déterminer efficacement s'il contient un élément donné. La liste, si je me souviens bien, fait une recherche linéaire, qui (pour un grand nombre d'éléments) est inefficace.

+0

+1 pour une bonne explication du problème original, et un invisible spécial +1 pour la mention de 'HashSet'; ce n'est pas quelque chose que je fais dans mon propre code, mais je devrais !! – Domenic