7

ファイルパスを含む配列があります。MD5に基づいて複製されたファイルのリストを作成したいと思います。私は次のように彼らのMD5を計算します:

private void calcMD5(Array files)  //Array contains a path of all files
{
    int i=0;
    string[] md5_val = new string[files.Length];
    foreach (string file_name in files)
    {
        using (var md5 = MD5.Create())
        {
            using (var stream = File.OpenRead(file_name))
            {
                md5_val[i] = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
                i += 1;
            }
        }
    }                
}

上記からMD5を計算できましたが、重複しているファイルのリストのみを取得する方法です。同じことを行う他の方法がある場合は、私に知らせてください。また、私はLinqを初めて使用します。

4

5 に答える 5

11

1.calcMD5関数を書き直して、単一のファイルパスを取り、MD5を返します。可能であれば、
2.ファイル名を型なし配列ではなく、string[]またはに格納します。次のLINQを使用して、同じハッシュを持つファイルのグループを取得します。List<string>
3.

var groupsOfFilesWithSameHash = files
  // or files.Cast<string>() if you're stuck with an Array
   .GroupBy(f => calcMD5(f))
   .Where(g => g.Count() > 1);

4.foreachネストされたループを持つグループにアクセスできます。次に例を示します。

foreach(var group in groupsOfFilesWithSameHash)
{
    Console.WriteLine("Shared MD5: " + g.Key);
    foreach (var file in group)
        Console.WriteLine("    " + file);
}
于 2013-02-28T11:16:29.270 に答える
2
    static void Main(string[] args)
    {
        // returns a list of file names, which have duplicate MD5 hashes
        var duplicates = CalcDuplicates(new[] {"Hello.txt", "World.txt"});
    }

    private static IEnumerable<string> CalcDuplicates(IEnumerable<string> fileNames)
    {
        return fileNames.GroupBy(CalcMd5OfFile)
                        .Where(g => g.Count() > 1)
                        // skip SelectMany() if you'd like the duplicates grouped by their hashes as group key
                        .SelectMany(g => g);
    }

    private static string CalcMd5OfFile(string path)
    {
        // I took your implementation - I don't know if there are better ones
        using (var md5 = MD5.Create())
        {
            using (var stream = File.OpenRead(path))
            {
                return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
            }
        }
    }
于 2013-02-28T11:22:14.477 に答える
0
var duplicates = md5_val.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key);

これにより、配列内で複製されたハッシュのリストが表示されます。

ハッシュの代わりに名前を取得するには:

var duplicates = md5_val.Select((x,i) => new Tuple<string, int>(x, i))
                        .GroupBy(x => x.Item1)
                        .Where(x => x.Count() > 1)
                        .SelectMany(x => files[x.Item2].ToList());
于 2013-02-28T11:12:57.313 に答える
0

MD5がハッシュするすべてのファイルの配列を返す代わりに、次のようにします。

  • 単一の'calculateFileHash()'メソッドがあります。
  • テストするファイル名の配列を作成します。
  • これを行う:

    var dupes = Filenames.GroupBy(fn =>calculateFileHash(fn))。Where(gr => gr.Count> 1);

これにより、グループの配列が返されます。各グループは、互いに同一の内容のファイル名を含む列挙型です。

于 2013-02-28T11:17:48.627 に答える
0
    private void calcMD5(String[] filePathes)  //Array contains a path of all files
    {
        Dictionary<String, String> hashToFilePathes = new Dictionary<String, String>();
        foreach (string file_name in filePathes)
        {
            using (var md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(file_name))
                {
                    //This will get you dictionary where key is md5hash and value is filepath
                    hashToFilePathes.Add(BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower(), file_name);
                }
            }
        }
        // Here will be all duplicates
        List<String> listOfDuplicates = hashToFilePathes.GroupBy(e => e.Key).Where(e => e.Count() > 1).SelectMany(e=>e).Select(e => e.Value).ToList();
    }
} 
于 2013-02-28T11:28:48.593 に答える