2010-12-08 4 views
1
 var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories).Select(x => new { x.Name, x.Length }); 
    var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories).Select(x => new { x.Name, x.Length }); 
    var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.Name }); 
    File.WriteAllLines(@"d:\log1.txt", foo1); 

Ici je compare deux fichiers basés sur le nom et l'écriture dans un fichier texte ... mais je dois écrire le nom avec le nom de répertoire ... Mais je ne peux pas sélectionner le nom du répertoire comme celui-cicomparer deux dossiers pour les fichiers non identiques?

var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.Name,x.DirectoryName }); 

Une suggestion?

+0

Tous les noms de répertoire seront les mêmes, pourquoi avez-vous besoin de les garder à le résultat de la requête LINQ? Juste le prendre de dir1. –

Répondre

3

L'utilisation de FullName résout-elle votre problème?

var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.FullName }); 

Sinon, vous pouvez mettre en place une chaîne personnalisée dans l'instruction Select:

// get strings in the format "file.ext, c:\path\to\file" 
var onlyIn1 = dir1Files.Except(dir2Files).Select(x => 
        string.Format("{0}, {1}", x.Name, x.Directory.FullName)); 

Afin de pouvoir utiliser ces informations dans les objets, ne créent pas des types anonymes avec des informations limitées dans les premiers pas, mais plutôt garder les objets FileInfo plein:

var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories); 
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories); 

Mise à jour
Le véritable problème dans votre exemple de code est que Except sera comparé à l'aide du comparateur d'égalité par défaut. Pour la plupart des types (et certainement dans le cas des types anonymes) cela signifie qu'il va comparer les références d'objets. Puisque vous avez deux listes avec des objets FileInfo, Except renverra tous les objets de la première liste, où les mêmes instances d'objet sont introuvables dans la seconde. Comme aucune des instances d'objet de la première liste n'est présente dans la seconde, tous les objets de la première liste seront retournés.

Afin de résoudre ce problème (et avoir toujours accès aux données que vous souhaitez stocker), vous devrez utiliser le Except overload that accepts an IEqualityComparer<T>. Tout d'abord, nous allons créer le IEqualityComparer:

class FileInfoComparer : IEqualityComparer<FileInfo> 
{ 
    public bool Equals(FileInfo x, FileInfo y) 
    { 
     // if x and y are the same instance, or both are null, they are equal 
     if (object.ReferenceEquals(x,y)) 
     { 
      return true; 
     } 
     // if one is null, they are not equal 
     if (x==null || y == null) 
     { 
      return false; 
     } 
     // compare Length and Name 
     return x.Length == y.Length && 
      x.Name.Equals(y.Name, StringComparison.OrdinalIgnoreCase); 
    } 

    public int GetHashCode(FileInfo obj) 
    { 
     return obj.Name.GetHashCode()^obj.Length.GetHashCode(); 
    } 
} 

Maintenant, vous pouvez utiliser ce comparateur pour comparer les fichiers dans les répertoires:

var dir1 = new DirectoryInfo(@"c:\temp\a"); 
var dir2 = new DirectoryInfo(@"c:\temp\b"); 

var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories); 
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories); 

var onlyIn1 = dir1Files 
    .Except(dir2Files, new FileInfoComparer()) 
    .Select(x => string.Format("{0}, {1}", x.Name, x.Directory.FullName)); 
+0

@Fredrik Mörk: je ne peux pas donner comme ça..je compare les fichiers basés sur le nom et la longueur seulement..mais je dois écrire à la fois le nom et le nom du répertoire .... si je mets x et point signifie qu'il montre uniquement le nom et longueur seulement – bala3569

+0

Plutôt que de sélectionner de nouveaux {x.Nom, x.Longueur}, sélectionnez simplement (x => x), vous aurez alors l'objet entier avec lequel filtrer. – Tom

+0

@ bala3569: J'ai manqué que vous créez un type anonyme dans les deux premières étapes. Comme le souligne @Tom, il suffit de retourner 'x' (ce qui signifie en fait que vous pouvez ignorer complètement l'appel' Select'). Je mettrai à jour ma réponse pour refléter ceci. –

Questions connexes