2010-12-08 15 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); 

ここで私は ...テキストファイルに名前と書き込みに基づいて2つのファイルを比較していますが、私はディレクトリ名と一緒に名前を書く必要が...しかし、私はこの同一でないファイルの2つのフォルダを比較していますか?

var onlyIn1 = dir1Files.Except(dir2Files).Select(x => new { x.Name,x.DirectoryName }); 
のようなディレクトリ名を選択することはできません

提案がありますか?

+0

すべてのディレクトリ名が同じになり、なぜあなたはそれらを維持する必要がありますかLINQクエリの結果?ちょうどそれをdir1から取る。 –

答えて

3

FullNameはあなたの問題を解決しましたか?

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

代わりにあなたが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)); 

オブジェクトにこの情報を使用することができるようにするために、中に限られた情報と匿名型を作成しないでください最初のステップではなく、完全なFileInfoオブジェクトを保持:

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

アップデート
コードサンプルの実際の問題は、Exceptデフォルトの等価比較ツールを使用して比較することです。ほとんどの型(確かに匿名型の場合)は、オブジェクト参照を比較することを意味します。 FileInfoのオブジェクトを持つ2つのリストがあるため、Exceptは、最初のリストからすべてのオブジェクトを返します。同じオブジェクトインスタンスが2番目のリストに見つかりません。最初のリストのオブジェクトインスタンスはいずれも2番目のリストに存在しないので、最初のリストのすべてのオブジェクトが返されます。

これを修正するには(まだ保存したいデータにアクセスするため)、Except overload that accepts an IEqualityComparer<T>を使用する必要があります。まずは、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(); 
    } 
} 

今、あなたは、ディレクトリ内のファイルを比較するために、その比較子を使用することができます。

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

@FredrikMörk:私はそれを与えることはできません。私は名前と長さだけに基づいてファイルを比較しています。しかし、私は名前とディレクトリ名の両方を書く必要があります....私はxとドットを置く場合は、長さのみ – bala3569

+0

新しい{x.Name、x.Length}を選択するのではなく、(x => x)を選択すると、フィルタリングするオブジェクト全体が表示されます。 – Tom

+0

@ bala3569:最初の2つのステップで匿名タイプを作成することができませんでした。 @Tomが指摘するように、 'x'を返すだけです(これは実質的に' Select'への呼び出しをスキップできることを意味します)。私はこれを反映するために私の答えを更新します。 –

関連する問題